#include <string>
#include <fstream>

//#include <grpcpp/ext/proto_server_reflection_plugin.h>
#include <grpcpp/grpcpp.h>
//#include <grpcpp/health_check_service_interface.h>

#include "pqc-sdf.grpc.pb.h"

#include "MyLog.h"
#include "sdf_0018_utility.h"

//// 密码卡接口
//#include "DJCcdAPI.h"

#include "sdf_gmt_0018.h"

static util::MyLog MLog("/var/log/dj_sdf_grpc_client.log");

static std::atomic_int g_grpcIsInit{0};
static std::unique_ptr<pqc::sdf::SDFService::Stub> g_grpcSdfStub;
static std::shared_ptr<grpc::Channel> g_grpcChannel;

static std::string g_ip;
static std::string g_port;
static std::string g_appName;
static std::string g_appPin;

#define PQC_CFG_INFO                ("/etc/pqccfg.init")

#define ACCESS_RIGHT_PASSWORD       ("11111111")

static std::string StringToHex(const char *input, size_t inputLen)
{
    std::string hexMessage;
    hexMessage.resize(inputLen * 2);
    for (size_t i = 0; i < inputLen; ++i)
    {
        snprintf(&hexMessage[2 * i], hexMessage.size(), "%02X", input[i] & 0xff);
    }

    return hexMessage;
}

static std::string StringToHex(const std::string &input)
{
    std::string hexMessage;
    hexMessage.resize(input.size() * 2);
    for (size_t i = 0; i < input.size(); ++i)
    {
        snprintf(&hexMessage[2 * i], hexMessage.size(), "%02X", input[i] & 0xff);
    }

    return hexMessage;
}

std::string HexToString(const char *hex, size_t hexLen)
{
    if (0 != hexLen % 2)
    {
        return "";
    }

    std::string message;
    for (size_t i = 0; i < hexLen / 2; ++i)
    {
        int value = 0;
        sscanf(&hex[2 * i], "%02X", (unsigned int*)&value);
        message.push_back((char)value);
    }

    return message;
}

std::string HexToString(const std::string &hexMessage)
{
    if (0 != hexMessage.size() % 2)
    {
        return "";
    }

    std::string message;
    for (size_t i = 0; i < hexMessage.size() / 2; ++i)
    {
        int value = 0;
        sscanf(&hexMessage[2 * i], "%02X", (unsigned int*)&value);
        message.push_back((char)value);
    }

    return message;
}

static int readFileInfo(const std::string &strFilePath, std::string &fileBuf)
{
    std::ifstream inFile(strFilePath.c_str(), std::ios::in | std::ios::binary);
    if (!inFile) {
        LOG_ERROR("Failed to ifstream file: {}.", strFilePath);
        return -1;
    }

    inFile.seekg(0, std::ios::end);
    size_t fileSize = inFile.tellg();
    inFile.seekg(0, std::ios::beg);

    fileBuf.clear();
    fileBuf.resize(fileSize);
    if (!inFile.read(&fileBuf[0], fileSize)) {
        LOG_ERROR("Failed to read file: {}, size: {}.", strFilePath, fileSize);
        inFile.close();
        return -1;
    }

    inFile.close();
    return 0;
}

static void Split(const std::string &strSplit, const std::string &strDelim, std::vector<std::string> &vecString)
{
    if (strSplit.empty() || strDelim.empty())
    {
        return;
    }

    const char *space = " \f\n\r\t\v";
    std::string notDelimStr(space);
    notDelimStr.push_back(strDelim[0]);

    /* 查找字符串分隔开始位置 */
    std::size_t iStartPos = strSplit.find_first_not_of(notDelimStr);
    while (iStartPos != std::string::npos)
    {
        /* 查找分隔字符串结尾 */
        std::size_t iEndPos = strSplit.find(strDelim, iStartPos);
        if (iEndPos != std::string::npos)
        {
            vecString.push_back(strSplit.substr(iStartPos, iEndPos - iStartPos));
        }
        else
        {
            /* 已经到尾部 */
            std::size_t spaceEndPos = strSplit.find_first_of(space, iStartPos);
            if (spaceEndPos != std::string::npos)
            {
                // 结尾有空格
                vecString.push_back(strSplit.substr(iStartPos, spaceEndPos - iStartPos));
            }
            else
            {
                vecString.push_back(strSplit.substr(iStartPos));
            }
            break;
        }

        /* 查找下一个分隔字符串开头位置 */
        iStartPos = strSplit.find_first_not_of(notDelimStr, iEndPos + strDelim.size());
    }
}

int SDF_Initialize(const char *ip, const char *port, const char *appName, const char *appPin)
{
    if (NULL == ip || '\0' == *ip)
    {
        LOG_ERROR("NULL or emtpy ip.");
        return -1;
    }

    if (NULL == port || '\0' == *port)
    {
        LOG_ERROR("NULL or emtpy port.");
        return -1;
    }

    if (NULL == appName || '\0' == *appName)
    {
        LOG_ERROR("NULL or emtpy appName.");
        return -1;
    }

    if (NULL == appPin || '\0' == *appPin)
    {
        LOG_ERROR("NULL or emtpy appPin.");
        return -1;
    }

    LOG_INFO("##########Start to init grpc ip: [{}], port: [{}]##########", ip, port);
    if (1 == g_grpcIsInit)
    {
        LOG_INFO("SDF is initialized.");
        return 0;
    }

    g_grpcIsInit = 0;

    g_grpcChannel = grpc::CreateChannel(std::string(ip) + ":" + port, grpc::InsecureChannelCredentials());
    if (nullptr == g_grpcChannel)
    {
        LOG_INFO("Failed to grpc create channel for SDF Stub.");
        return -1;
    }
    LOG_INFO("GRPC sdf CreateChannel get state: [{}]", g_grpcChannel->GetState(true));

    g_grpcSdfStub = pqc::sdf::SDFService::NewStub(g_grpcChannel);
    if (nullptr == g_grpcSdfStub)
    {
        LOG_INFO("Failed to grpc new sdf stub.");
        return -1;
    }
    LOG_INFO("Succeed to new grpc SDF stub, channel status: {}", g_grpcChannel->GetState(true));

    g_ip = ip;
    g_port = port;
    g_appName = appName;
    g_appPin = appPin;
    g_grpcIsInit = 1;
    LOG_INFO("##########Succeed to init grpc##########");
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_OpenDevice
* 功能描述： // 打开设备
* 输入参数： //
* 输出参数： // phDeviceHandle       设备句柄
* 返 回 值： // 0                    成功
                非0                  失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_OpenDevice(OUT void** phDeviceHandle)
{
    LOG_INFO("Start to open device.");

    int nRet = 0;

    if (0 == g_grpcIsInit)
    {
        std::string filePath = PQC_CFG_INFO;

        std::string fileBuf;
        nRet= readFileInfo(filePath, fileBuf);
        if (0 != nRet) {
            LOG_ERROR("Failed to read file: [{}]", filePath);
            return nRet;
        }
        LOG_INFO("File buf: [{}]", fileBuf);

        std::vector<std::string> vecString;
        Split(fileBuf, ",", vecString);
        if (4 > vecString.size())
        {
            LOG_ERROR("Invalid cfg info size: [{}]", vecString.size());
            return -1;
        }

        std::string ip = vecString[0];
        std::string port = vecString[1];
        std::string appName = vecString[2];
        std::string appPin = vecString[3];
        LOG_INFO("Ip: [{}], port: [{}], appName: [{}], appPin[{}].", ip, port, appName, appPin);

        nRet = SDF_Initialize(ip.c_str(), port.c_str(), appName.c_str(), appPin.c_str());
        if (0 != nRet) {
            LOG_ERROR("Failed to pqc sdf init.");
            return nRet;
        }

        g_grpcIsInit = 1;
        LOG_INFO("Grpc is init.");
    }

    pqc::sdf::OpenDeviceRequest request;
    pqc::sdf::OpenDeviceResponse reply;
    grpc::ClientContext context;

    request.set_appname(g_appName);
    request.set_apppin(g_appPin);

    grpc::Status status = g_grpcSdfStub->SDF_OpenDevice(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_OpenDevice status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_OpenDevice, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    void *hDeviceHandle = (void*)new int64_t();
    if (NULL != hDeviceHandle)
    {
        *phDeviceHandle = hDeviceHandle;
    }
    *((int64_t*)*phDeviceHandle) = (int64_t)reply.devicehandle();

    LOG_INFO("Succeed to open device handle: [{}]", *((int64_t*)*phDeviceHandle));
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_CloseDevice
* 功能描述： // 关闭设备
* 输入参数： // phDeviceHandle       已打开的设备句柄
* 输出参数： //
* 返 回 值： // 0                    成功
                非0                  失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_CloseDevice(IN void* hDeviceHandle)
{
    if (NULL == hDeviceHandle)
    {
        LOG_ERROR("NULL hDeviceHandle.");
        return -1;
    }

    LOG_INFO("Start to close device handle: [{}]", *((int64_t*)hDeviceHandle));

    pqc::sdf::CloseDeviceRequest request;
    pqc::sdf::CommonResponse reply;
    grpc::ClientContext context;

    request.set_devicehandle(*(int64_t*)hDeviceHandle);
    delete (int64_t*)hDeviceHandle;
    hDeviceHandle = NULL;

    grpc::Status status = g_grpcSdfStub->SDF_CloseDevice(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_CloseDevice status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_CloseDevice, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    LOG_INFO("Succeed to close device handle.");
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_OpenSession
* 功能描述： // 创建会话
* 输入参数： // phDeviceHandle       已打开的设备句柄
* 输出参数： // phSessionHandle      返回与密码设备建立的新的会话句柄
* 返 回 值： // 0                    成功
                非0                  失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_OpenSession(IN void* hDeviceHandle, OUT void** phSessionHandle)
{
    LOG_INFO("Start to device handle: [{}]", *((int64_t*)hDeviceHandle));

    pqc::sdf::OpenSessionRequest request;
    pqc::sdf::OpenSessionResponse reply;
    grpc::ClientContext context;

    request.set_devicehandle(*(int64_t*)hDeviceHandle);
    grpc::Status status = g_grpcSdfStub->SDF_OpenSession(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_OpenSession status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_OpenSession, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    void *hSessionHandle = (void*)new int64_t();
    if (NULL != hSessionHandle)
    {
        *phSessionHandle = hSessionHandle;
    }
    *((int64_t*)*phSessionHandle) = (int64_t)reply.sessionhandle();

    LOG_INFO("Succeed to open device handle: [{}], session handle: [{}]", *((int64_t*)hDeviceHandle), *((int64_t*)*phSessionHandle));
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_OpenSession
* 功能描述： // 关闭会话
* 输入参数： // phSessionHandle      与密码设备已建立的会话句柄
* 输出参数： //
* 返 回 值： // 0                    成功
                非0                  失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_CloseSession(IN void* hSessionHandle)
{
    if (NULL == hSessionHandle)
    {
        LOG_ERROR("NULL hSessionHandle.");
        return -1;
    }
    LOG_INFO("Start to close session handle: [{}]", *((int64_t*)hSessionHandle));

    pqc::sdf::CloseSessionRequest request;
    pqc::sdf::CommonResponse reply;
    grpc::ClientContext context;

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    delete (int64_t*)hSessionHandle;
    hSessionHandle = NULL;

    grpc::Status status = g_grpcSdfStub->SDF_CloseSession(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_CloseSession status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_CloseSession, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    LOG_INFO("Succeed to close session handle.");
    return 0;
}

#if 0
std::string PingPong(const char *pingData, int pingDataLen)
{
    pqc::sdf::PingPongRequest request;
    pqc::sdf::PingPongResponse reply;
    grpc::ClientContext context;

    request.set_ping(pingData, pingDataLen);

    grpc::Status status = g_grpcSdfStub->PingPong(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc PingPong status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return "";
    }
    return reply.pong();
}
#endif

/**********************************************************************
* 函数名称： // SDF_GetDeviceInfo
* 功能描述： // 获取设备信息
* 输入参数： // phSessionHandle      与密码设备已建立的会话句柄
* 输出参数： // pstDeviceInfo        设备能力描述信息
* 返 回 值： // 0                    成功
                非0                  失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_GetDeviceInfo(IN void* hSessionHandle, OUT DEVICEINFO *pstDeviceInfo)
{
    LOG_INFO("Session handle: [{}]", *((int64_t*)hSessionHandle));

    pqc::sdf::DeviceInfoRequest request;
    pqc::sdf::DeviceInfoResponse reply;
    grpc::ClientContext context;

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    grpc::Status status = g_grpcSdfStub->SDF_GetDeviceInfo(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_GetDeviceInfo status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_GetDeviceInfo, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    ::pqc::sdf::RpcDeviceInfo rpcDeviceInfo = reply.device_info();
//  snprintf((char*)pstDeviceInfo->IssuerName, sizeof(pstDeviceInfo->IssuerName), "%s", rpcDeviceInfo.issuername().c_str());
    snprintf((char*)pstDeviceInfo->IssuerName, sizeof(pstDeviceInfo->IssuerName), "%s", "pqctech");
    snprintf((char*)pstDeviceInfo->DeviceName, sizeof(pstDeviceInfo->DeviceName), "%s", "PQ-HSM");
    snprintf((char*)pstDeviceInfo->DeviceSerial, sizeof(pstDeviceInfo->DeviceSerial), "%s", rpcDeviceInfo.deviceserial().c_str());

//  pstDeviceInfo->DeviceVersion = rpcDeviceInfo.deviceversion();
    pstDeviceInfo->DeviceVersion = 2;
    pstDeviceInfo->StandardVersion = rpcDeviceInfo.standardversion();
    pstDeviceInfo->AsymAlgAbility[0] = rpcDeviceInfo.asymalgability(0);
    pstDeviceInfo->AsymAlgAbility[1] = rpcDeviceInfo.asymalgability(1);
    pstDeviceInfo->SymAlgAbility = rpcDeviceInfo.symalgability();
    pstDeviceInfo->HashAlgAbility = rpcDeviceInfo.hashalgability();
    pstDeviceInfo->BufferSize = rpcDeviceInfo.buffersize();

    LOG_INFO("Succeed to SDF_GetDeviceInfo.");
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_GenerateRandom
* 功能描述： // 产生随机数
* 输入参数： // phSessionHandle      与密码设备已建立的会话句柄
                uiLength             欲获取的随机数长度
* 输出参数： // pucRandom            缓冲区指针，用于存放获取的随机数
* 返 回 值： // 0                    成功
                非0                  失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_GenerateRandom(IN void* hSessionHandle, IN unsigned int uiLength, OUT unsigned char *pucRandom)
{
//  LOG_INFO("Session handle: [{}], uiLength: [{}]", *((int64_t*)hSessionHandle), uiLength);

    pqc::sdf::GenerateRandomRequest request;
    pqc::sdf::GenerateRandomResponse reply;
    grpc::ClientContext context;

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_uilength(uiLength);
    grpc::Status status = g_grpcSdfStub->SDF_GenerateRandom(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_GenerateRandom status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_GenerateRandom, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    std::string random = reply.pucrandom();
    memcpy(pucRandom, &random[0], random.size());

//  LOG_INFO("Succeed to gen random: 0x[{}]", StringToHex(random));
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_GetPrivateKeyAccessRight
* 功能描述： // 获取私钥权限
* 输入参数： // phSessionHandle      与密码设备已建立的会话句柄
                uiKeyIndex           存储私钥的索引值
                pucPassword          使用私钥权限的标识码
                uiPwdLength          私钥访问控制码长度，不少于8字节
* 输出参数： //
* 返 回 值： // 0                    成功
                非0                  失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_GetPrivateKeyAccessRight(IN void* hSessionHandle, IN unsigned int uiKeyIndex, IN unsigned char *pucPassword, IN unsigned int uiPwdLength)
{
    LOG_INFO("Start to uiKeyIndex: [{}], pucPassword: [{}], uiPwdLength: [{}]", uiKeyIndex, std::string((char*)pucPassword, uiPwdLength), uiPwdLength);

    pqc::sdf::GetPrivateKeyAccessRightRequest request;
    pqc::sdf::CommonResponse reply;
    grpc::ClientContext context;

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_uikeyindex(uiKeyIndex);
    request.set_pucpassword(pucPassword, uiPwdLength);
    grpc::Status status = g_grpcSdfStub->SDF_GetPrivateKeyAccessRight(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_GetPrivateKeyAccessRight status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_GetPrivateKeyAccessRight, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    LOG_INFO("Succeed to SDF_GetPrivateKeyAccessRight.");
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_ReleasePrivateKeyAccessRight
* 功能描述： // 释放私钥权限
* 输入参数： // phSessionHandle      与密码设备已建立的会话句柄
                uiKeyIndex           存储私钥的索引值
* 输出参数： //
* 返 回 值： // 0                    成功
                非0                  失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_ReleasePrivateKeyAccessRight(IN void* hSessionHandle, IN unsigned int uiKeyIndex)
{
    LOG_INFO("uiKeyIndex: [{}]", uiKeyIndex);

    pqc::sdf::UiKeyIndexRequest request;
    pqc::sdf::CommonResponse reply;
    grpc::ClientContext context;

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_uikeyindex(uiKeyIndex);
    grpc::Status status = g_grpcSdfStub->SDF_ReleasePrivateKeyAccessRight(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_ReleasePrivateKeyAccessRight status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_ReleasePrivateKeyAccessRight, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    LOG_INFO("Succeed to SDF_ReleasePrivateKeyAccessRight.");
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_ExportSignPublicKey_RSA
* 功能描述： // 导出密码设备内部存储的指定索引位置的RSA签名公钥
* 输入参数： // phSessionHandle      与密码设备已建立的会话句柄
                uiKeyIndex           存储RSA密钥对的索引值
* 输出参数： // pucPublicKey         RSA公钥结构
* 返 回 值： // 0                    成功
                非0                  失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_ExportSignPublicKey_RSA(IN void* hSessionHandle, IN unsigned int uiKeyIndex, OUT RSArefPublicKey *pucPublicKey)
{
    LOG_INFO("uiKeyIndex: [{}]", uiKeyIndex);

    pqc::sdf::RSAExportKeyRequest request;
    pqc::sdf::RSAKeyResponse reply;
    grpc::ClientContext context;

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_uikeyindex(uiKeyIndex);
    grpc::Status status = g_grpcSdfStub->SDF_ExportSignPublicKey_RSA(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_ExportSignPublicKey_RSA status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_ExportSignPublicKey_RSA, reply rv: [{}]", reply.rv());
        return reply.rv();
    }
    LOG_INFO("ASN1 pucPublicKey: [{}]", reply.keybytes());

    int nRet = RSA_PublicKey_PEMTo0018(reply.keybytes(), pucPublicKey);
    if (0 != nRet)
    {
        LOG_ERROR("Failed to RSA_PublicKey_PEMTo0018: [{}]", reply.keybytes());
        return nRet;
    }

    LOG_INFO("Succeed to SDF_ExportSignPublicKey_RSA.");
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_ExportEncPublicKey_RSA
* 功能描述： // 导出密码设备内部存储的指定索引位置的RSA加密公钥
* 输入参数： // phSessionHandle      与密码设备已建立的会话句柄
                uiKeyIndex           存储RSA密钥对的索引值
* 输出参数： // pucPublicKey         RSA公钥结构
* 返 回 值： // 0                    成功
                非0                  失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_ExportEncPublicKey_RSA(IN void* hSessionHandle, IN unsigned int uiKeyIndex, OUT RSArefPublicKey *pucPublicKey)
{
    LOG_INFO("uiKeyIndex: [{}]", uiKeyIndex);

    pqc::sdf::RSAExportKeyRequest request;
    pqc::sdf::RSAKeyResponse reply;
    grpc::ClientContext context;

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_uikeyindex(uiKeyIndex);
    grpc::Status status = g_grpcSdfStub->SDF_ExportEncPublicKey_RSA(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_ExportEncPublicKey_RSA status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_ExportEncPublicKey_RSA, reply rv: [{}]", reply.rv());
        return reply.rv();
    }
    LOG_INFO("ASN1 pucPublicKey: [{}]", reply.keybytes());

    int nRet = RSA_PublicKey_PEMTo0018(reply.keybytes(), pucPublicKey);
    if (0 != nRet)
    {
        LOG_ERROR("Failed to RSA_PublicKey_PEMTo0018: [{}]", reply.keybytes());
        return nRet;
    }

    LOG_INFO("Succeed to SDF_ExportEncPublicKey_RSA.");
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_GenerateKeyPair_RSA
* 功能描述： // 请求密码设备产生指定模长的RSA密钥对
* 输入参数： // phSessionHandle      与密码设备已建立的会话句柄
                uiKeyBits            指定密钥模长
* 输出参数： // pucPublicKey         RSA公钥结构
                pucPrivateKey        RSA密钥结构
* 返 回 值： // 0                    成功
                非0                  失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_GenerateKeyPair_RSA(IN void* hSessionHandle, IN unsigned int uiKeyBits, OUT RSArefPublicKey *pucPublicKey, OUT RSArefPrivateKey *pucPrivateKey)
{
    LOG_INFO("uiKeyBits: [{}]", uiKeyBits);

    pqc::sdf::SDF_GenerateKeyPair_RSARequest request;
    pqc::sdf::SDF_GenerateKeyPair_RSAResponse reply;
    grpc::ClientContext context;

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_uikeybits(uiKeyBits);
    grpc::Status status = g_grpcSdfStub->SDF_GenerateKeyPair_RSA(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_GenerateKeyPair_RSA status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_GenerateKeyPair_RSA, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    LOG_INFO("ASN1 pucPublicKey: [{}], pucPrivateKey: [{}]", reply.pubkeybytes(), reply.prikeybytes());
    int nRet = RSA_PublicKey_PEMTo0018(reply.pubkeybytes(), pucPublicKey);
    if (0 != nRet)
    {
        LOG_ERROR("Failed to RSA_PublicKey_PEMTo0018: [{}]", reply.pubkeybytes());
        return nRet;
    }

    nRet = RSA_PrivateKey_PEMTo0018(reply.prikeybytes(), pucPrivateKey);
    if (0 != nRet)
    {
        LOG_ERROR("Failed to RSA_PrivateKey_PEMTo0018: [{}]", reply.prikeybytes());
        return nRet;
    }

    LOG_INFO("Succeed to SDF_GenerateKeyPair_RSA.");
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_GenerateKeyWithIPK_RSA
* 功能描述： // 生成会话密钥并用指定索引的内部加密公钥公钥加密输出，同时返回密钥句柄
* 输入参数： // phSessionHandle      与密码设备已建立的会话句柄
                uiIPKIndex           存储公钥的索引值
                uiKeyBits            指定产生的会话密钥长度
* 输出参数： // pucKey               缓冲区指针，用于存放返回的密钥密文
                puiKeyLength         返回的密钥密文的长度
                phKeyHandle          返回的密钥句柄
* 返 回 值： // 0                    成功
                非0                  失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_GenerateKeyWithIPK_RSA(IN void* hSessionHandle, IN unsigned int uiIPKIndex , IN unsigned int uiKeyBits, OUT unsigned char *pucKey, OUT unsigned int *puiKeyLength, OUT void** phKeyHandle)
{
    LOG_INFO("uiIPKIndex: [{}], uiKeyBits: [{}]", uiIPKIndex, uiKeyBits);

    pqc::sdf::SDF_GenerateKeyWithIPK_RSARequest request;
    pqc::sdf::SDF_GenerateKeyWithIPK_RSAResponse reply;
    grpc::ClientContext context;

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_uiipkindex(uiIPKIndex);
    request.set_uikeybits(uiKeyBits);
    grpc::Status status = g_grpcSdfStub->SDF_GenerateKeyWithIPK_RSA(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_GenerateKeyWithIPK_RSA status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_GenerateKeyWithIPK_RSA, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    std::string key = reply.puckey();
    memcpy(pucKey, &key[0], key.size());
    *puiKeyLength = key.size();

    void *hkeyHandle = (void*)new int64_t();
    if (NULL != hkeyHandle)
    {
        *phKeyHandle = hkeyHandle;
    }
    *((int64_t*)*phKeyHandle) = (int64_t)reply.phkeyhandle();

    LOG_INFO("Succeed to SDF_GenerateKeyWithIPK_RSA, phKeyHandle: [{}], key: 0x[{}]", *((int64_t*)*phKeyHandle), StringToHex(key));
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_GenerateKeyWithEPK_RSA
* 功能描述： // 生成会话密钥并用外部加密公钥公钥加密输出，同时返回密钥句柄
* 输入参数： // phSessionHandle      与密码设备已建立的会话句柄
                uiKeyBits            指定产生的会话密钥长度
                pucPublicKey         输入的外部RSA公钥结构
* 输出参数： // pucKey               缓冲区指针，用于存放返回的密钥密文
                puiKeyLength         返回的密钥密文的长度
                phKeyHandle          返回的密钥句柄
* 返 回 值： // 0                    成功
                非0                  失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_GenerateKeyWithEPK_RSA(IN void* hSessionHandle, IN unsigned int uiKeyBits, IN RSArefPublicKey *pucPublicKey, OUT unsigned char *pucKey, OUT unsigned int *puiKeyLength, OUT void* *phKeyHandle)
{
    pqc::sdf::SDF_GenerateKeyWithEPK_RSARequest request;
    pqc::sdf::SDF_GenerateKeyWithEPK_RSAResponse reply;
    grpc::ClientContext context;

    std::string pemPubkey = RSA_PublicKey_0018ToPEM(pucPublicKey);
    if (pemPubkey.empty())
    {
        LOG_ERROR("Failed to RSA_PublicKey_0018ToPEM.");
        return -1;
    }

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_uikeybits(uiKeyBits);
    request.set_pucpublickey(pemPubkey);
    grpc::Status status = g_grpcSdfStub->SDF_GenerateKeyWithEPK_RSA(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_GenerateKeyWithEPK_RSA status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_GenerateKeyWithEPK_RSA, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    std::string key = reply.puckey();
    memcpy(pucKey, &key[0], key.size());
    *puiKeyLength = key.size();

    void *hkeyHandle = (void*)new int64_t();
    if (NULL != hkeyHandle)
    {
        *phKeyHandle = hkeyHandle;
    }
    *((int64_t*)*phKeyHandle) = (int64_t)reply.phkeyhandle();

    return 0;
}

/**********************************************************************
* 函数名称： // SDF_ImportKeyWithISK_RSA
* 功能描述： // 导入会话密钥并用内部私钥解密，同时返回密钥句柄
* 输入参数： // phSessionHandle      与密码设备已建立的会话句柄
                uiISKIndex           加密私钥的索引值，对应于加密时的公钥
                pucKey               缓冲区指针，用于存放输入的密钥密文
                puiKeyLength         返回的密钥密文的长度
* 输出参数： // phKeyHandle          返回的密钥句柄
* 返 回 值： // 0                    成功
                非0                  失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_ImportKeyWithISK_RSA(IN void* hSessionHandle, IN unsigned int uiISKIndex, IN unsigned char *pucKey, IN unsigned int puiKeyLength, OUT void* *phKeyHandle)
{
    LOG_INFO("uiISKIndex: [{}], pucKey: 0x[{}], puiKeyLength: [{}]", uiISKIndex, StringToHex((char*)pucKey, puiKeyLength), puiKeyLength);

    pqc::sdf::SDF_ImportKeyWithISK_RSARequest request;
    pqc::sdf::SDF_ImportKeyWithISK_RSAResponse reply;
    grpc::ClientContext context;

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_uiiskindex(uiISKIndex);
    request.set_puckey(pucKey, puiKeyLength);
    grpc::Status status = g_grpcSdfStub->SDF_ImportKeyWithISK_RSA(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_ImportKeyWithISK_RSA status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_ImportKeyWithISK_RSA, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    void *hkeyHandle = (void*)new int64_t();
    if (NULL != hkeyHandle)
    {
        *phKeyHandle = hkeyHandle;
    }
    *((int64_t*)*phKeyHandle) = (int64_t)reply.phkeyhandle();

    LOG_INFO("Succeed to SDF_ImportKeyWithISK_RSA, phKeyHandle: [{}]", *((int64_t*)*phKeyHandle));
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_ExchangeDigitEnvelopeBaseOnRSA
* 功能描述： // 将由内部加密公钥加密的会话密钥转换为由外部指定公钥加密，可用于数字信封转换
* 输入参数： // phSessionHandle      与密码设备已建立的会话句柄
                uiKeyIndex           存储RSA密钥对的索引值
                pucPublicKey         外部RSA公钥结构
                pucDEInput           缓冲区指针，用于存放输入的会话密钥密文
                uiDELength           会话密钥密文的长度
* 输出参数： // pucDEOutput          缓冲区指针，用于存放输出的密钥密文
                puiDELength          输出的会话密钥密文的长度
* 返 回 值： // 0                    成功
                非0                  失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_ExchangeDigitEnvelopeBaseOnRSA(IN void* hSessionHandle, IN unsigned int uiKeyIndex, IN RSArefPublicKey *pucPublicKey, IN unsigned char *pucDEInput, IN unsigned int uiDELength, OUT unsigned char *pucDEOutput, OUT unsigned int *puiDELength)
{
    LOG_INFO("uiKeyIndex: [{}], pucDEInput: 0x[{}], uiDELength: [{}]", uiKeyIndex, StringToHex((char*)pucDEInput, uiDELength), uiDELength);

    pqc::sdf::SDF_ExchangeDigitEnvelopeBaseOnRSARequest request;
    pqc::sdf::SDF_ExchangeDigitEnvelopeBaseOnRSAResponse reply;
    grpc::ClientContext context;

    std::string pemPubkey = RSA_PublicKey_0018ToPEM(pucPublicKey);
    if (pemPubkey.empty())
    {
        LOG_ERROR("Failed to RSA_PublicKey_0018ToPEM.");
        return -1;
    }
    LOG_INFO("RSA PEM public key: [{}]", pemPubkey);

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_uikeyindex(uiKeyIndex);
    request.set_pucpublickey(pemPubkey);
    request.set_pucdeinput(pucDEInput, uiDELength);
    grpc::Status status = g_grpcSdfStub->SDF_ExchangeDigitEnvelopeBaseOnRSA(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_ExchangeDigitEnvelopeBaseOnRSA status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_ExchangeDigitEnvelopeBaseOnRSA, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    std::string deout = reply.pucdeoutput();
    memcpy(pucDEOutput, &deout[0], deout.size());
    *puiDELength = deout.size();

    LOG_INFO("Succeed to SDF_ExchangeDigitEnvelopeBaseOnRSA, pucDEOutput: 0x[{}], len: [{}]", StringToHex(deout), *puiDELength);
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_ExportSignPublicKey_ECC
* 功能描述： // 导出密码设备内部存储的指定索引位置的ECC签名公钥
* 输入参数： // phSessionHandle      与密码设备已建立的会话句柄
                uiKeyIndex           存储ECC密钥对的索引值
* 输出参数： // pucPublicKey         ECC公钥结构
* 返 回 值： // 0                    成功
                非0                  失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_ExportSignPublicKey_ECC(IN void* hSessionHandle, IN unsigned int uiKeyIndex, OUT ECCrefPublicKey *pucPublicKey)
{
    pqc::sdf::SDF_ExportSignPublicKey_ECCRequest request;
    pqc::sdf::SDF_ExportSignPublicKey_ECCResponse reply;
    grpc::ClientContext context;

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_uikeyindex(uiKeyIndex);
    grpc::Status status = g_grpcSdfStub->SDF_ExportSignPublicKey_ECC(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_ExportSignPublicKey_ECC status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_ExportSignPublicKey_ECC, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    int isBinStr;
    std::string eccPubkey = reply.pucpublickey();
    int nRet = SM2_PublicKey_ASN1To0018(&eccPubkey[0], eccPubkey.size(), pucPublicKey, isBinStr);

//  int nRet = RSA_PublicKey_PEMTo0018(reply.pucpublickey(), pucPublicKey);
    if (0 != nRet)
    {
        LOG_ERROR("Failed to SM2_PublicKey_ASN1To0018: [{}]", reply.pucpublickey());
        return nRet;
    }

    return 0;
}

/**********************************************************************
* 函数名称： // SDF_ExportEncPublicKey_ECC
* 功能描述： // 导出密码设备内部存储的指定索引位置的ECC加密公钥
* 输入参数： // phSessionHandle      与密码设备已建立的会话句柄
                uiKeyIndex           存储ECC密钥对的索引值
* 输出参数： // pucPublicKey         ECC公钥结构
* 返 回 值： // 0                    成功
                非0                  失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_ExportEncPublicKey_ECC(IN void* hSessionHandle, IN unsigned int uiKeyIndex, OUT ECCrefPublicKey *pucPublicKey)
{
    pqc::sdf::SDF_ExportEncPublicKey_ECCRequest request;
    pqc::sdf::SDF_ExportEncPublicKey_ECCResponse reply;
    grpc::ClientContext context;

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_uikeyindex(uiKeyIndex);
    grpc::Status status = g_grpcSdfStub->SDF_ExportEncPublicKey_ECC(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_ExportEncPublicKey_ECC status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_ExportEncPublicKey_ECC, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    int isBinStr;
    std::string eccPubkey = reply.pucpublickey();
    int nRet = SM2_PublicKey_ASN1To0018(&eccPubkey[0], eccPubkey.size(), pucPublicKey, isBinStr);

//  int nRet = RSA_PublicKey_PEMTo0018(reply.pucpublickey(), pucPublicKey);
    if (0 != nRet)
    {
        LOG_ERROR("Failed to RSA_PublicKey_PEMTo0018: [{}]", reply.pucpublickey());
        return nRet;
    }

    return 0;
}

/**********************************************************************
* 函数名称： // SDF_GenerateKeyPair_ECC
* 功能描述： // 请求密码设备产生指定类型和模长的ECC密钥对
* 输入参数： // phSessionHandle      与密码设备已建立的会话句柄
                uiAlgID              指定算法标识
                uiKeyBits            指定密钥长度
* 输出参数： // pucPublicKey         ECC公钥结构
                pucPrivateKey        ECC私钥结构
* 返 回 值： // 0                    成功
                非0                  失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_GenerateKeyPair_ECC(IN void* hSessionHandle, IN unsigned int  uiAlgID, IN unsigned int uiKeyBits, OUT ECCrefPublicKey *pucPublicKey, OUT ECCrefPrivateKey *pucPrivateKey)
{
    LOG_INFO("uiAlgID: 0x[{:08X}], uiKeyBits: [{}]", uiAlgID, uiKeyBits);
    pqc::sdf::SDF_GenerateKeyPair_ECCRequest request;
    pqc::sdf::SDF_GenerateKeyPair_ECCResponse reply;
    grpc::ClientContext context;

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_uialgid(uiAlgID);
    request.set_uikeybits(uiKeyBits);
    grpc::Status status = g_grpcSdfStub->SDF_GenerateKeyPair_ECC(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_GenerateKeyPair_ECC status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_GenerateKeyPair_ECC, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

#if 0
    std::string eccPubKey = reply.pubkey();
    int nRet = SM2_PublicKey_BinStrTo0018(eccPubKey, pucPublicKey);
    if (0 != nRet)
    {
        LOG_ERROR("Failed to SM2_PublicKey_BinStrTo0018: 0x[{}].", StringToHex(eccPubKey));
        return nRet;
    }
    LOG_INFO("pucPublicKey: 0x[{}]", StringToHex(eccPubKey));

    std::string eccPriKey = reply.prikey();
    nRet = SM2_PrivateKey_BinStrTo0018(eccPriKey, pucPrivateKey);
    if (0 != nRet)
    {
        LOG_ERROR("Failed to SM2_PrivateKey_BinStrTo0018: 0x[{}].", StringToHex(eccPriKey));
        return nRet;
    }
    LOG_INFO("pucPrivateKey: 0x[{}]", StringToHex(eccPriKey));
#endif

    int isBinStr;
    std::string eccPubKey = reply.pubkey();
    int nRet = SM2_PublicKey_ASN1To0018(&eccPubKey[0], eccPubKey.size(), pucPublicKey, isBinStr);
    if (0 != nRet)
    {
        LOG_ERROR("Failed to SM2_PublicKey_ASN1To0018: [{}], continue.", StringToHex(eccPubKey));
        return nRet;
    }
    LOG_INFO("pucPublicKey ASN1: [{}]", StringToHex(eccPubKey));

    std::string eccPriKey = reply.prikey();
    nRet = SM2_PrivateKey_ASN1To0018(&eccPriKey[0], eccPriKey.size(), pucPrivateKey, isBinStr);
    if (0 != nRet)
    {
        LOG_ERROR("Failed to SM2_PrivateKey_ASN1To0018: [{}], continue.", StringToHex(eccPriKey));
        return nRet;
    }
    LOG_INFO("pucPrivateKey ASN1: [{}]", StringToHex(eccPriKey));

    return 0;
}

/**********************************************************************
* 函数名称： // SDF_GenerateKeyWithIPK_ECC
* 功能描述： // 生成会话密钥并用内部ECC公钥加密输出
* 输入参数： // phSessionHandle      与密码设备已建立的会话句柄
                uiIPKIndex           存储公钥的索引值
                uiKeyBits            指定产生的会话密钥长度
* 输出参数： // pucKey               缓冲区指针，用于存放返回的密钥密文
                phKeyHandle          返回的密钥句柄
* 返 回 值： // 0                    成功
                非0                  失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_GenerateKeyWithIPK_ECC(IN void* hSessionHandle, IN unsigned int uiIPKIndex, IN unsigned int uiKeyBits, OUT ECCCipher *pucKey, OUT void** phKeyHandle)
{
    LOG_INFO("uiIPKIndex: [{}], uiKeyBits: [{}]", uiIPKIndex, uiKeyBits);

    pqc::sdf::SDF_GenerateKeyWithIPK_ECCRequest request;
    pqc::sdf::SDF_GenerateKeyWithIPK_ECCResponse reply;
    grpc::ClientContext context;

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_uikeyindex(uiIPKIndex);
    request.set_uikeybits(uiKeyBits);
    grpc::Status status = g_grpcSdfStub->SDF_GenerateKeyWithIPK_ECC(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_GenerateKeyWithIPK_ECC status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_GenerateKeyWithIPK_ECC, reply rv: [{}]", reply.rv());
        return reply.rv();
    }
    LOG_INFO("Key ECC Cipher: 0x[{}]", StringToHex(reply.puckey()));

    int isBinStr;
    int nRet = SM2_Cipher_ASN1To0018(reply.puckey(), pucKey, isBinStr);
    if (0 != nRet)
    {
        LOG_ERROR("Failed to SM2_Cipher_ASN1To0018: [{}]", reply.puckey());
        return nRet;
    }

    void *hkeyHandle = (void*)new int64_t();
    if (NULL != hkeyHandle)
    {
        *phKeyHandle = hkeyHandle;
    }
    *((int64_t*)*phKeyHandle) = (int64_t)reply.phkeyhandle();

    LOG_INFO("Succeed to SDF_GenerateKeyWithIPK_ECC, key handle: [{}]", *((int64_t*)*phKeyHandle));
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_GenerateKeyWithEPK_ECC
* 功能描述： // 生成会话密钥并用外部ECC公钥加密输出
* 输入参数： // phSessionHandle      与密码设备已建立的会话句柄
                uiKeyBits            指定产生的会话密钥长度
                uiAlgID              外部ECC公钥的算法标识
                pucPublicKey         输入的外部ECC公钥结构
* 输出参数： // pucKey               缓冲区指针，用于存放返回的密钥密文
                phKeyHandle          返回的密钥句柄
* 返 回 值： // 0                    成功
                非0                  失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_GenerateKeyWithEPK_ECC(IN void* hSessionHandle, IN unsigned int uiKeyBits, IN unsigned int uiAlgID, IN ECCrefPublicKey*pucPublicKey, OUT ECCCipher*pucKey, OUT void* *phKeyHandle)
{
    LOG_INFO("Start to uiKeyBits: [{}], uiAlgID: [{:08X}].", uiKeyBits, uiAlgID);

    pqc::sdf::SDF_GenerateKeyWithEPK_ECCRequest request;
    pqc::sdf::SDF_GenerateKeyWithEPK_ECCResponse reply;
    grpc::ClientContext context;

    std::string asn1Pubkey = SM2_PublicKey_0018ToASN1(pucPublicKey);
    if (asn1Pubkey.empty())
    {
        LOG_ERROR("Failed to SM2_PublicKey_0018ToASN1.");
        return -1;
    }
    LOG_INFO("ASN1 public key: 0x[{}]", StringToHex(asn1Pubkey));

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_uikeybits(uiKeyBits);
    request.set_uialgid(uiAlgID);
    request.set_pucpublickey(asn1Pubkey);
    grpc::Status status = g_grpcSdfStub->SDF_GenerateKeyWithEPK_ECC(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_GenerateKeyWithEPK_ECC status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_GenerateKeyWithEPK_ECC, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    int isBinStr;
    int nRet = SM2_Cipher_ASN1To0018(reply.puckey(), pucKey, isBinStr);
    if (0 != nRet)
    {
        LOG_ERROR("Failed to SM2_Cipher_ASN1To0018: [{}]", reply.puckey());
        return nRet;
    }

    void *hkeyHandle = (void*)new int64_t();
    if (NULL != hkeyHandle)
    {
        *phKeyHandle = hkeyHandle;
    }
    *((int64_t*)*phKeyHandle) = (int64_t)reply.phkeyhandle();

    LOG_INFO("Succeed to SDF_GenerateKeyWithEPK_ECC, key handle: [{}]", *((int64_t*)*phKeyHandle));
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_ImportKeyWithISK_ECC
* 功能描述： // 导入会话密钥并用内部ECC私钥解密，同时返回密钥句柄
* 输入参数： // phSessionHandle      与密码设备已建立的会话句柄
                uiISKIndex           存储私钥的索引值，对应于加密时的公钥
                pucKey               缓冲区指针，用于存放输入的密钥密文
                pucPublicKey         输入的外部ECC公钥结构
* 输出参数： // phKeyHandle          返回的密钥句柄
* 返 回 值： // 0                    成功
                非0                  失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_ImportKeyWithISK_ECC(IN void* hSessionHandle, IN unsigned int uiISKIndex, IN  ECCCipher *pucKey, OUT void* *phKeyHandle)
{
    LOG_INFO("uiISKIndex: [{}]", uiISKIndex);

    pqc::sdf::SDF_ImportKeyWithISK_ECCRequest request;
    pqc::sdf::SDF_ImportKeyWithISK_ECCResponse reply;
    grpc::ClientContext context;

    std::string asn1Cipher = SM2_Cipher_0018ToASN1(pucKey);
    if (asn1Cipher.empty())
    {
        LOG_ERROR("Failed to SM2_Cipher_0018ToASN1.");
        return -1;
    }
    LOG_INFO("ASN1 ecc cipher: 0x[{}]", StringToHex(asn1Cipher));

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_uiiskindex(uiISKIndex);
    request.set_puckey(asn1Cipher);
    grpc::Status status = g_grpcSdfStub->SDF_ImportKeyWithISK_ECC(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_ImportKeyWithISK_ECC status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_ImportKeyWithISK_ECC, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    void *hkeyHandle = (void*)new int64_t();
    if (NULL != hkeyHandle)
    {
        *phKeyHandle = hkeyHandle;
    }
    *((int64_t*)*phKeyHandle) = (int64_t)reply.phkeyhandle();

    LOG_INFO("Succeed to SDF_ImportKeyWithISK_ECC, phKeyHandle: [{}]", *((int64_t*)*phKeyHandle));
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_GenerateAgreementDataWithECC
* 功能描述： // 使用ECC密钥协商算法，为计算会话密钥而产生协商参数
* 输入参数： // phSessionHandle      与密码设备已建立的会话句柄
                uiISKIndex           存储私钥的索引值，对应于加密时的公钥
                uiKeyBits            要求协商的密钥长度
                pucSponsorID         参与密钥协商的发起方ID
                uiSponsorIDLength    发起方ID长度
* 输出参数： // pucSponsorPublicKey  发起方ECC公钥结构
                purSponsorTmpPublicKey发起方临时ECC公钥结构
                phAgreementHandle    协商句柄
* 返 回 值： // 0                    成功
                非0                  失败，返回错误码
* 其它说明： // 协商的发起方首先调用本函数
***********************************************************************/
int SDF_GenerateAgreementDataWithECC(IN void* hSessionHandle, IN unsigned int uiISKIndex, IN unsigned int uiKeyBits, IN unsigned char *pucSponsorID, IN unsigned int uiSponsorIDLength,
                                        OUT ECCrefPublicKey *pucSponsorPublicKey, OUT ECCrefPublicKey *pucSponsorTmpPublicKey, OUT void* *phAgreementHandle)
{
    LOG_INFO("hSessionHandle: [{}], uiISKIndex: [{}], uiKeyBits: [{}], pucSponsorID: [{}], uiSponsorIDLength: [{}]",
             *((int64_t*)hSessionHandle), uiISKIndex, uiKeyBits, std::string((char*)pucSponsorID, uiSponsorIDLength), uiSponsorIDLength);

    pqc::sdf::GenerateAgreementDataWithECCRequest request;
    pqc::sdf::GenerateAgreementDataWithECCResponse reply;
    grpc::ClientContext context;

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_uiiskindex(uiISKIndex);
    request.set_uikeybits(uiKeyBits);
    request.set_pucsponsorid(pucSponsorID, uiSponsorIDLength);
    grpc::Status status = g_grpcSdfStub->SDF_GenerateAgreementDataWithECC(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_GenerateAgreementDataWithECC status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_GenerateAgreementDataWithECC, reply rv: 0x[{:08x}]", reply.rv());
        return reply.rv();
    }
    LOG_INFO("ASN1 pucSponsorPublicKey: 0x[{}], ASN1 pucSponsorTmpPublicKey: 0x[{}]", StringToHex(reply.pucsponsorpublickey()), StringToHex(reply.pucsponsortmppublickey()));

    int isBinStr;
    std::string eccPubKey = reply.pucsponsorpublickey();
    int nRet = SM2_PublicKey_ASN1To0018(&eccPubKey[0], eccPubKey.size(), pucSponsorPublicKey, isBinStr);
    if (0 != nRet)
    {
        LOG_ERROR("Failed to SM2_PublicKey_ASN1To0018: [{}]", eccPubKey);
        return nRet;
    }
    LOG_INFO("Out ASN1 pucSponsorPublicKey: 0x[{}]", StringToHex(eccPubKey));

    std::string eccPubKeyTmp = reply.pucsponsortmppublickey();
    nRet = SM2_PublicKey_ASN1To0018(&eccPubKeyTmp[0], eccPubKeyTmp.size(), pucSponsorTmpPublicKey, isBinStr);
    if (0 != nRet)
    {
        LOG_ERROR("Failed to SM2_PublicKey_ASN1To0018: [{}]", eccPubKeyTmp);
        return nRet;
    }
    LOG_INFO("Out ASN1 pucSponsorTmpPublicKey: 0x[{}]", StringToHex(eccPubKeyTmp));

    void *hkeyHandle = (void*)new int64_t();
    if (NULL != hkeyHandle)
    {
        *phAgreementHandle = hkeyHandle;
    }
    *((int64_t *)*phAgreementHandle) = (int64_t)reply.phagreementhandle();

    LOG_INFO("Succeed to SDF_GenerateAgreementDataWithECC, phAgreementHandle: [{}]", *((int64_t *)*phAgreementHandle));
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_GenerateKeyWithECC
* 功能描述： // 使用ECC密钥协商算法，使用自身的协商句柄和响应方的协商参数计算会话密钥
* 输入参数： // phSessionHandle          与密码设备已建立的会话句柄
                pucResponseID            外部输入的响应方ID值
                uiResponseIDLength       外部输入的响应方ID长度
                pucResponsePublicKey     外部输入的响应方ECC公钥结构
                pucResponseTmpPublicKey  外部输入的响应方临时ECC公钥结构
                hAgreementHandle         协商句柄，用于计算协商密钥
* 输出参数： // phKeyHandle              返回的密钥句柄
* 返 回 值： // 0                    成功
                非0                  失败，返回错误码
* 其它说明： // 协商的发起方获得响应方的协商参数后调用本函数，计算会话密钥
***********************************************************************/
int SDF_GenerateKeyWithECC(IN void* hSessionHandle, IN unsigned char *pucResponseID, IN unsigned int uiResponseIDLength,
                              IN ECCrefPublicKey *pucResponsePublicKey, IN ECCrefPublicKey *pucResponseTmpPublicKey, IN void* hAgreementHandle, OUT void* *phKeyHandle)
{
    LOG_INFO("hSessionHandle: [{}], pucResponseID: [{}], uiResponseIDLength: [{}]", *((int64_t*)hSessionHandle), std::string((char*)pucResponseID, uiResponseIDLength), uiResponseIDLength);

    pqc::sdf::SDF_GenerateKeyWithECCRequest request;
    pqc::sdf::SDF_GenerateKeyWithECCResponse reply;
    grpc::ClientContext context;

    std::string asn1PubKey = SM2_PublicKey_0018ToASN1(pucResponsePublicKey);
    if (asn1PubKey.empty())
    {
        LOG_ERROR("Failed to SM2_PublicKey_0018ToASN1.");
        return -1;
    }
    LOG_INFO("Input ASN1 pucResponsePublicKey: 0x[{}]", StringToHex(asn1PubKey));

    std::string asn1PubKeyTmp = SM2_PublicKey_0018ToASN1(pucResponseTmpPublicKey);
    if (asn1PubKeyTmp.empty())
    {
        LOG_ERROR("Failed to SM2_PublicKey_0018ToASN1.");
        return -1;
    }
    LOG_INFO("Input ASN1 pucResponseTmpPublicKey: 0x[{}]", StringToHex(asn1PubKeyTmp));

    LOG_INFO("Input phAgreementHandle: [{}]", *((int64_t *)hAgreementHandle));

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_pucresponseid(pucResponseID, uiResponseIDLength);
    request.set_pucresponsepublickey(asn1PubKey);
    request.set_pucresponsetmppublickey(asn1PubKeyTmp);
    request.set_phagreementhandle(*(int64_t*)hAgreementHandle);
    grpc::Status status = g_grpcSdfStub->SDF_GenerateKeyWithECC(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_GenerateKeyWithECC status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_GenerateKeyWithECC, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    void *hkeyHandle = (void*)new int64_t();
    if (NULL != hkeyHandle)
    {
        *phKeyHandle = hkeyHandle;
    }
    *((int64_t *)*phKeyHandle) = (int64_t)reply.phkeyhandle();

    LOG_INFO("Succeed to SDF_GenerateKeyWithECC, phKeyHandle: [{}]", *((int64_t *)*phKeyHandle));
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_GenerateAgreementDataAndKeyWithECC
* 功能描述： // 使用ECC密钥协商算法，产生协商参数并计算会话密钥
* 输入参数： // phSessionHandle          与密码设备已建立的会话句柄
                uiISKIndex               私钥索引
                uiKeyBits                协商后输出的密钥长度
                pucResponseID            响应方ID值
                uiResponseIDLength       响应方ID长度
                pucSponsorID             发起方ID值
                uiSponsorIDLength        发起方ID长度
                pucSponsorPublicKey      外部输入的发起方ECC公钥结构
                pucSponsorTmpPublicKey   外部输入的发起方临时ECC公钥结构
* 输出参数： // pucResponsePublicKey     返回的响应方ECC公钥结构
                pucResponseTmpPublicKey  返回的响应方临时ECC公钥结构
                phKeyHandle              返回的密钥句柄
* 返 回 值： // 0                        成功
                非0                      失败，返回错误码
* 其它说明： // 本函数有响应方调用
***********************************************************************/
int SDF_GenerateAgreementDataAndKeyWithECC(IN void* hSessionHandle, IN unsigned int uiISKIndex, IN unsigned int uiKeyBits, IN unsigned char *pucResponseID, IN unsigned int uiResponseIDLength,
                                              IN unsigned char *pucSponsorID, IN unsigned int uiSponsorIDLength, IN ECCrefPublicKey *pucSponsorPublicKey, IN ECCrefPublicKey *pucSponsorTmpPublicKey,
                                              OUT ECCrefPublicKey *pucResponsePublicKey, OUT ECCrefPublicKey *pucResponseTmpPublicKey, OUT void* *phKeyHandle)
{
    LOG_INFO("hSessionHandle: [{}], uiISKIndex: [{}], uiKeyBits: [{}], pucResponseID: [{}], uiResponseIDLength: [{}], pucSponsorID: [{}], uiSponsorIDLength: [{}]",
             *((int64_t*)hSessionHandle), uiISKIndex, uiKeyBits, std::string((char*)pucResponseID, uiResponseIDLength), uiResponseIDLength, std::string((char*)pucSponsorID, uiSponsorIDLength), uiSponsorIDLength);
    int nRet = 0;

    pqc::sdf::SDF_GenerateAgreementDataAndKeyWithECCRequest request;
    pqc::sdf::SDF_GenerateAgreementDataAndKeyWithECCResponse reply;
    grpc::ClientContext context;

    std::string asn1SponsorPublicKey = SM2_PublicKey_0018ToASN1(pucSponsorPublicKey);
    if (asn1SponsorPublicKey.empty())
    {
        LOG_ERROR("Failed to SM2_PublicKey_0018ToASN1.");
        return -1;
    }
    LOG_INFO("Input ASN1 SponsorPublicKey: [{}]", StringToHex(asn1SponsorPublicKey));

    std::string asn1SponsorTmpPublicKey = SM2_PublicKey_0018ToASN1(pucSponsorTmpPublicKey);
    if (asn1SponsorTmpPublicKey.empty())
    {
        LOG_ERROR("Failed to SM2_PublicKey_0018ToASN1.");
        return -1;
    }
    LOG_INFO("Input ASN1 SponsorTmpPublicKey: [{}]", StringToHex(asn1SponsorTmpPublicKey));

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_uiiskindex(uiISKIndex);
    request.set_uikeybits(uiKeyBits);
    request.set_pucresponseid(pucResponseID, uiResponseIDLength);
    request.set_pucsponsorid(pucSponsorID, uiSponsorIDLength);
    request.set_pucsponsorpublickey(asn1SponsorPublicKey);
    request.set_pucsponsortmppublickey(asn1SponsorTmpPublicKey);
    grpc::Status status = g_grpcSdfStub->SDF_GenerateAgreementDataAndKeyWithECC(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_GenerateAgreementDataAndKeyWithECC status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_GenerateAgreementDataAndKeyWithECC, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    int isBinStr;
    std::string eccPubKey = reply.pucresponsepublickey();
    nRet = SM2_PublicKey_ASN1To0018(&eccPubKey[0], eccPubKey.size(), pucResponsePublicKey, isBinStr);
    if (0 != nRet)
    {
        LOG_ERROR("Failed to SM2_PublicKey_ASN1To0018: [{}]", eccPubKey);
        return nRet;
    }
    LOG_INFO("Output ASN1 pucResponsePublicKey: [{}]", StringToHex(eccPubKey));

    std::string eccPubKeyTmp = reply.pucresponsetmppublickey();
    nRet = SM2_PublicKey_ASN1To0018(&eccPubKeyTmp[0], eccPubKeyTmp.size(), pucResponseTmpPublicKey, isBinStr);
    if (0 != nRet)
    {
        LOG_ERROR("Failed to SM2_PublicKey_ASN1To0018: [{}]", eccPubKeyTmp);
        return nRet;
    }
    LOG_INFO("Output ASN1 pucResponseTmpPublicKey: [{}]", StringToHex(eccPubKeyTmp));

    void *hkeyHandle = (void*)new int64_t();
    if (NULL != hkeyHandle)
    {
        *phKeyHandle = hkeyHandle;
    }
    *((int64_t *)*phKeyHandle) = (int64_t)reply.phkeyhandle();

    LOG_INFO("Succeed to SDF_GenerateAgreementDataAndKeyWithECC, phKeyHandle: [{}]", *((int64_t *)*phKeyHandle));
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_ExchangeDigitEnvelopeBaseOnECC
* 功能描述： // 将由内部加密的会话密钥转换为由外部指定的公钥加密，可用于数字信封转换
* 输入参数： // phSessionHandle          与密码设备已建立的会话句柄
                uiKeyIndex               存储ECC密钥对的索引值
                uiAlgID                  外部ECC公钥的算法标识
                pucPublicKey             外部ECC公钥结构
                pucEnDataIn              缓冲区指针，用于存放输入的会话密钥密文
* 输出参数： // pucEnDataOut             缓冲区指针，用于存放输出的会话密钥密文
* 返 回 值： // 0                        成功
                非0                      失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_ExchangeDigitEnvelopeBaseOnECC(IN void* hSessionHandle, IN unsigned int uiKeyIndex, IN unsigned int uiAlgID,
                                          IN ECCrefPublicKey *pucPublicKey, IN ECCCipher *pucEnDataIn, OUT ECCCipher *pucEnDataOut)
{
    LOG_INFO("hSessionHandle: [{}], uiKeyIndex: [{}], uiAlgID: [0x{:08x}]", *((int64_t*)hSessionHandle), uiKeyIndex, uiAlgID);
    int nRet = 0;
    pqc::sdf::SDF_ExchangeDigitEnvelopeBaseOnECCRequest request;
    pqc::sdf::SDF_ExchangeDigitEnvelopeBaseOnECCResponse reply;
    grpc::ClientContext context;

    std::string asn1PubKey = SM2_PublicKey_0018ToASN1(pucPublicKey);
    if (asn1PubKey.empty())
    {
        LOG_ERROR("Failed to SM2_PublicKey_0018ToASN1.");
        return -1;
    }
    LOG_INFO("ECC pubkey ASN1: [{}]", StringToHex(asn1PubKey));

    std::string asn1Cipher = SM2_Cipher_0018ToASN1(pucEnDataIn);
    if (asn1Cipher.empty())
    {
        LOG_ERROR("Failed to SM2_Cipher_0018ToASN1.");
        return -1;
    }
    LOG_INFO("ECC Cipher ASN1: [{}]", StringToHex(asn1Cipher));

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_uikeyindex(uiKeyIndex);
    request.set_uialgid(uiAlgID);
    request.set_pucpublickey(asn1PubKey);
    request.set_pucencdatain(asn1Cipher);
    grpc::Status status = g_grpcSdfStub->SDF_ExchangeDigitEnvelopeBaseOnECC(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_ExchangeDigitEnvelopeBaseOnECC status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_ExchangeDigitEnvelopeBaseOnECC, reply rv: [{}]", reply.rv());
        return reply.rv();
    }
    LOG_INFO("ECC Cipher encrypt out data: [{}]", StringToHex(reply.pucencdataout()));

    int isBinStr;
    nRet = SM2_Cipher_ASN1To0018(reply.pucencdataout(), pucEnDataOut, isBinStr);
    if (0 != nRet)
    {
        LOG_ERROR("Failed to SM2_Cipher_ASN1To0018: [{}]", reply.pucencdataout());
        return nRet;
    }

    LOG_INFO("Succeed to SDF_ExchangeDigitEnvelopeBaseOnECC.");
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_GenerateKeyWithKEK
* 功能描述： // 生成会话密钥并用密钥加密密钥加密输出
* 输入参数： // phSessionHandle          与密码设备已建立的会话句柄
                uiKeyBits                产生的会话密钥长度
                uiAlgID                  算法标识，指定对称加密算法
                uiKEKIndex               存储密钥加密密钥的索引值
* 输出参数： // pucKey                   缓冲区指针，用于存放返回的密钥密文
                puiKeyLength             返回的密钥密文长度
                phKeyHandle              返回的密钥句柄
* 返 回 值： // 0                        成功
                非0                      失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_GenerateKeyWithKEK(IN void* hSessionHandle, IN unsigned int uiKeyBits, IN unsigned int uiAlgID, IN unsigned int uiKEKIndex,
                              OUT unsigned char *pucKey, OUT unsigned int *puiKeyLength, OUT void* *phKeyHandle)
{
    LOG_INFO("uiKeyBits: [{}], uiAlgID: [{:08X}], uiKEKIndex: [{}]", uiKeyBits, uiAlgID, uiKEKIndex);



    pqc::sdf::SDF_GenerateKeyWithKEKRequest request;
    pqc::sdf::SDF_GenerateKeyWithKEKResponse reply;
    grpc::ClientContext context;

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_uikeybits(uiKeyBits);
    request.set_uialgid(uiAlgID);
    request.set_uikekindex(uiKEKIndex);
    grpc::Status status = g_grpcSdfStub->SDF_GenerateKeyWithKEK(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_GenerateKeyWithKEK status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_GenerateKeyWithKEK, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    std::string key = reply.puckey();
    memcpy(pucKey, &key[0], key.size());
    *puiKeyLength = key.size();
    LOG_INFO("Key: 0x[{}]", StringToHex((char*)pucKey, *puiKeyLength));

    void *hkeyHandle = (void*)new int64_t();
    if (NULL != hkeyHandle)
    {
        *phKeyHandle = hkeyHandle;
    }
    *((int64_t *)*phKeyHandle) = (int64_t)reply.phkeyhandle();

    LOG_INFO("Succeed to SDF_GenerateKeyWithKEK, key handle: [{}]", *((int64_t *)*phKeyHandle));
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_ImportKeyWithKEK
* 功能描述： // 导入会话密钥并用密钥加密密钥解密
* 输入参数： // phSessionHandle          与密码设备已建立的会话句柄
                uiAlgID                  算法标识，指定对称加密算法
                uiKEKIndex               存储密钥加密密钥的索引值
                pucKey                   缓冲区指针，用于存放输入的密钥密文
                puiKeyLength             输入的密钥密文长度
* 输出参数： // phKeyHandle              返回的密钥句柄
* 返 回 值： // 0                        成功
                非0                      失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_ImportKeyWithKEK(IN void* hSessionHandle, IN unsigned int uiAlgID, IN unsigned int uiKEKIndex, IN unsigned char *pucKey, IN unsigned int puiKeyLength, OUT void* *phKeyHandle)
{
    pqc::sdf::ImportKeyWithKEKRequest request;
    pqc::sdf::ImportKeyWithKEKResponse reply;
    grpc::ClientContext context;

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_uialgid(uiAlgID);
    request.set_uikekindex(uiKEKIndex);
    request.set_puckey(pucKey, puiKeyLength);
    grpc::Status status = g_grpcSdfStub->SDF_ImportKeyWithKEK(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_ImportKeyWithKEK status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_ImportKeyWithKEK, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    void *hkeyHandle = (void*)new int64_t();
    if (NULL != hkeyHandle)
    {
        *phKeyHandle = hkeyHandle;
    }
    *((int64_t *)*phKeyHandle) = (int64_t)reply.phkeyhandle();
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_ImportKey
* 功能描述： // 导入明文会话密钥
* 输入参数： // phSessionHandle          与密码设备已建立的会话句柄
                pucKey                   缓冲区指针，用于存放输入的密钥
                puiKeyLength             输入的密钥密文长度
* 输出参数： // phKeyHandle              返回的密钥句柄
* 返 回 值： // 0                        成功
                非0                      失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_ImportKey(IN void* hSessionHandle, IN unsigned char *pucKey, IN unsigned int puiKeyLength, OUT void* *phKeyHandle)
{
    LOG_INFO("Start to import key len: [{}]", puiKeyLength);

    pqc::sdf::SDF_ImportKeyRequest request;
    pqc::sdf::SDF_ImportKeyResponse reply;
    grpc::ClientContext context;

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_puckey(pucKey, puiKeyLength);
    grpc::Status status = g_grpcSdfStub->SDF_ImportKey(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_ImportKey status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_ImportKey, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    void *hkeyHandle = (void*)new int64_t();
    if (NULL != hkeyHandle)
    {
        *phKeyHandle = hkeyHandle;
    }
    *((int64_t *)*phKeyHandle) = (int64_t)reply.phkeyhandle();

    LOG_INFO("Succeed to import key: [{}], key handle: [{}]", *((int64_t *)*phKeyHandle), (int64_t)(*phKeyHandle));
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_DestoryKey
* 功能描述： // 销毁会话密钥
* 输入参数： // phSessionHandle          与密码设备已建立的会话句柄
                phKeyHandle              返回的密钥句柄
* 输出参数： //
* 返 回 值： // 0                        成功
                非0                      失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_DestroyKey(IN void* hSessionHandle, IN void* pKeyHandle)
{
    if (NULL == pKeyHandle) {
        LOG_ERROR("Null key handle.");
        return -1;
    }
    LOG_INFO("Start to destory key: 0x[{}], key handle: [{}]", *(int64_t*)pKeyHandle, (int64_t)pKeyHandle);

    pqc::sdf::SDF_DestroyKeyRequest request;
    pqc::sdf::CommonResponse reply;
    grpc::ClientContext context;

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_phkeyhandle(*(int64_t*)pKeyHandle);
    delete (int64_t*)pKeyHandle;
    pKeyHandle = NULL;

    grpc::Status status = g_grpcSdfStub->SDF_DestroyKey(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_DestroyKey status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_DestroyKey, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    LOG_INFO("Succeed to SDF_DestroyKey.");
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_ExternalPublicKeyOperation_RSA
* 功能描述： // 使用外部公钥对数据进行运算
* 输入参数： // phSessionHandle          与密码设备已建立的会话句柄
                pucPublicKey             外部RSA公钥结构
                pucDataInput             缓冲区指针，用于存放输入的数据
                uiInputLength            输入的数据长度
* 输出参数： // pucDataOutput            缓冲区指针，用于存放输出的数据
                puiOutputLength          输出的数据长度
* 返 回 值： // 0                        成功
                非0                      失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_ExternalPublicKeyOperation_RSA(IN void* hSessionHandle, IN RSArefPublicKey *pucPublicKey,
                                          IN unsigned char *pucDataInput, IN unsigned int uiInputLength,
                                          OUT unsigned char *pucDataOutput, OUT unsigned int *puiOutputLength)
{
    pqc::sdf::SDF_ExternalPublicKeyOperation_RSARequest request;
    pqc::sdf::OperationRSAResponse reply;
    grpc::ClientContext context;

    std::string pemPubkey = RSA_PublicKey_0018ToPEM(pucPublicKey);
    if (pemPubkey.empty())
    {
        LOG_ERROR("Failed to RSA_PublicKey_0018ToPEM.");
        return -1;
    }

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_pucpublickey(pemPubkey);
    request.set_pucdatainput(pucDataInput, uiInputLength);
    grpc::Status status = g_grpcSdfStub->SDF_ExternalPublicKeyOperation_RSA(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_ExternalPublicKeyOperation_RSA status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_ExternalPublicKeyOperation_RSA, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    std::string data = reply.pucdataoutput();
    memcpy(pucDataOutput, &data[0], data.size());
    *puiOutputLength = data.size();
    return 0;
}

int SDF_ExternalPrivateKeyOperation_RSA(IN void* hSessionHandle, IN RSArefPrivateKey *pucPrivateKey,
                                           IN unsigned char *pucDataInput, IN unsigned int uiInputLength,
                                           OUT unsigned char *pucDataOutput, OUT unsigned int *puiOutputLength)
{
    LOG_INFO("pucDataInput: 0x[{}], uiInputLength: [{}], RSA private bits: [{}]", StringToHex((char*)pucDataInput, uiInputLength), uiInputLength, pucPrivateKey->bits);
    pqc::sdf::ExternalPrivateKeyOperationRSARequest request;
    pqc::sdf::OperationRSAResponse reply;
    grpc::ClientContext context;

    std::string privateKey;
    std::string publicKey;
    int nRet = RSA_PrivateKey_0018ToPEM("", pucPrivateKey, privateKey, publicKey);
    if (0 != nRet)
    {
        LOG_ERROR("Failed to RSA_PrivateKey_0018ToPEM.");
        return -1;
    }

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_pucprivatekey(privateKey);
    request.set_pucdatainput(pucDataInput, uiInputLength);
    grpc::Status status = g_grpcSdfStub->SDF_ExternalPrivateKeyOperation_RSA(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_ExternalPrivateKeyOperation_RSA status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_ExternalPrivateKeyOperation_RSA, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    std::string data = reply.pucdataoutput();
    memcpy(pucDataOutput, &data[0], data.size());
    *puiOutputLength = data.size();

    LOG_INFO("Succeed to SDF_ExternalPrivateKeyOperation_RSA, output data: 0x[{}], len: [{}]", StringToHex(data), *puiOutputLength);
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_InternalPublicKeyOperation_RSA
* 功能描述： // 使用内部公钥对数据进行运算
* 输入参数： // phSessionHandle          与密码设备已建立的会话句柄
                uiKeyIndex               存储公钥的索引值
                pucDataInput             缓冲区指针，用于存放输入的数据
                uiInputLength            输入的数据长度
* 输出参数： // pucDataOutput            缓冲区指针，用于存放输出的数据
                puiOutputLength          输出的数据长度
* 返 回 值： // 0                        成功
                非0                      失败，返回错误码
* 其它说明： // 索引范围仅限于内部签名密钥对
***********************************************************************/
int SDF_InternalPublicKeyOperation_RSA(IN void* hSessionHandle, IN unsigned int uiKeyIndex,
                                          IN unsigned char *pucDataInput, IN unsigned int uiInputLength,
                                          OUT unsigned char *pucDataOutput, OUT unsigned int *puiOutputLength)
{
    LOG_INFO("uiKeyIndex: [{}], pucDataInput: 0x[{}], uiInputLength: 0x[{}]", uiKeyIndex, StringToHex((char*)pucDataInput, uiInputLength), uiInputLength);

    pqc::sdf::InternalPublicKeyOperationRSARequest request;
    pqc::sdf::OperationRSAResponse reply;
    grpc::ClientContext context;

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_uikeyindex(uiKeyIndex);
    request.set_pucdatainput(pucDataInput, uiInputLength);
    grpc::Status status = g_grpcSdfStub->SDF_InternalPublicKeyOperation_RSA(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_InternalPublicKeyOperation_RSA status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_InternalPublicKeyOperation_RSA, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    std::string data = reply.pucdataoutput();
    memcpy(pucDataOutput, &data[0], data.size());
    *puiOutputLength = data.size();

    LOG_INFO("Succeed to SDF_InternalPublicKeyOperation_RSA, output data: 0x[{}]", StringToHex((char*)pucDataOutput, *puiOutputLength));
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_InternalPrivateKeyOperation_RSA
* 功能描述： // 使用内部私钥对数据进行运算
* 输入参数： // phSessionHandle          与密码设备已建立的会话句柄
                uiKeyIndex               存储私钥的索引值
                pucDataInput             缓冲区指针，用于存放输入的数据
                uiInputLength            输入的数据长度
* 输出参数： // pucDataOutput            缓冲区指针，用于存放输出的数据
                puiOutputLength          输出的数据长度
* 返 回 值： // 0                        成功
                非0                      失败，返回错误码
* 其它说明： // 索引范围仅限于内部签名密钥对
***********************************************************************/
int SDF_InternalPrivateKeyOperation_RSA(IN void* hSessionHandle, IN unsigned int uiKeyIndex,
                                           IN unsigned char  *pucDataInput, IN unsigned int uiInputLength,
                                           OUT unsigned char *pucDataOutput, OUT unsigned int *puiOutputLength)
{
    LOG_INFO("uiKeyIndex: [{}], pucDataInput: 0x[{}], uiInputLength: [{}]", uiKeyIndex, StringToHex((char*)pucDataInput, uiInputLength), uiInputLength);
    pqc::sdf::InternalPrivateKeyOperationRSARequest request;
    pqc::sdf::OperationRSAResponse reply;
    grpc::ClientContext context;

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_uikeyindex(uiKeyIndex);
    request.set_pucdatainput(pucDataInput, uiInputLength);
    grpc::Status status = g_grpcSdfStub->SDF_InternalPrivateKeyOperation_RSA(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_InternalPrivateKeyOperation_RSA status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_InternalPrivateKeyOperation_RSA, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    std::string data = reply.pucdataoutput();
    memcpy(pucDataOutput, &data[0], data.size());
    *puiOutputLength = data.size();
    LOG_INFO("Succeed to SDF_InternalPrivateKeyOperation_RSA, output data: 0x[{}], len: [{}]", std::string((char*)pucDataOutput, *puiOutputLength), *puiOutputLength);
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_InternalSign_ECC
* 功能描述： // 使用内部ECC私钥对数据进行签名运算
* 输入参数： // phSessionHandle          与密码设备已建立的会话句柄
                uiISKIndex               内部ECC签名私钥索引
                pucData                  缓冲区指针，用于存放输入的数据
                uiDataLength             输入的数据长度
* 输出参数： // pucSignature             缓冲区指针，用于存放输出的签名值数据
* 返 回 值： // 0                        成功
                非0                      失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_InternalSign_ECC(IN void* hSessionHandle, IN unsigned int uiISKIndex, IN unsigned char *pucData, IN unsigned int uiDataLength, OUT ECCSignature *pucSignature)
{
    int nRet = 0;

    pqc::sdf::SDF_InternalSign_ECCRequest request;
    pqc::sdf::SDF_InternalSign_ECCResponse reply;
    grpc::ClientContext context;

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_uiiskindex(uiISKIndex);
    request.set_pucdata(pucData, uiDataLength);
    grpc::Status status = g_grpcSdfStub->SDF_InternalSign_ECC(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_InternalSign_ECC status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_InternalSign_ECC, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    int isBinStr;
    nRet = SM2_Signature_ASN1To0018(reply.pucsignature(), pucSignature, isBinStr);
    if (0 != nRet)
    {
        LOG_ERROR("Failed to call grpc SM2_Signature_BinStrTo0018.");
        return nRet;
    }

    LOG_INFO("Succeed to internal sign ECC.");
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_InternalVerify_ECC
* 功能描述： // 使用内部ECC公钥对ECC签名值进行验证
* 输入参数： // phSessionHandle          与密码设备已建立的会话句柄
                uiISKIndex               内部ECC签名私钥索引
                pucData                  缓冲区指针，用于存放输入的数据
                uiDataLength             输入的数据长度
                pucSignature             缓冲区指针，用于存放输入的签名值数据
* 输出参数： //
* 返 回 值： // 0                        成功
                非0                      失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_InternalVerify_ECC(IN void* hSessionHandle, IN unsigned int uiISKIndex, IN unsigned char *pucData, IN unsigned int uiDataLength, IN ECCSignature *pucSignature)
{
    pqc::sdf::SDF_InternalVerify_ECCRequest request;
    pqc::sdf::CommonResponse reply;
    grpc::ClientContext context;

    std::string asn1Sig = SM2_Signature_0018ToASN1(pucSignature);
    if (asn1Sig.empty())
    {
        LOG_ERROR("Failed to call grpc SM2_Signature_0018ToASN1.");
        return -1;
    }

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_uiiskindex(uiISKIndex);
    request.set_pucdata(pucData, uiDataLength);
    request.set_pucsignature(asn1Sig);
    grpc::Status status = g_grpcSdfStub->SDF_InternalVerify_ECC(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_InternalVerify_ECC status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_InternalVerify_ECC, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    LOG_INFO("Succeed to internal verify ECC.");
    return 0;
}

int SDF_ExternalSign_ECC(IN void* hSessionHandle, IN unsigned int uiAlgID, IN ECCrefPrivateKey *pucPrivateKey, IN unsigned char *pucData, IN unsigned int uiDataLength, OUT ECCSignature *pucSignature)
{
    LOG_INFO("uiAlgID: 0x[{:08X}], pucData: [{}]", uiAlgID, StringToHex((char*)pucData, uiDataLength));
    uiAlgID = SGD_SM2_1;
    pqc::sdf::SDF_ExternalSign_ECCRequest request;
    pqc::sdf::SDF_ExternalSign_ECCResponse reply;
    grpc::ClientContext context;

    std::string asn1Prikey = SM2_PrivateKey_0018ToASN1(pucPrivateKey);
    if (asn1Prikey.empty())
    {
        LOG_ERROR("Failed to call grpc SM2_PrivateKey_0018ToBinStr.");
        return -1;
    }
    LOG_INFO("pucPrivateKey bin: 0x[{}], pucData: 0x[{}]", StringToHex(asn1Prikey), StringToHex((char*)pucData, uiDataLength));

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_uialgid(uiAlgID);
    request.set_pucprivatekey(asn1Prikey);
    request.set_pucdata(pucData, uiDataLength);
    grpc::Status status = g_grpcSdfStub->SDF_ExternalSign_ECC(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_ExternalSign_ECC status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_ExternalSign_ECC, reply rv: [{}]", reply.rv());
        return reply.rv();
    }
    LOG_INFO("pucSignature ASN1: 0x[{}]", StringToHex(reply.pucsignature()));

    int isBinStr;
    int nRet = SM2_Signature_ASN1To0018(reply.pucsignature(), pucSignature, isBinStr);
    if (0 != nRet)
    {
        LOG_ERROR("Failed to call grpc SM2_Signature_BinStrTo0018.");
        return nRet;
    }

    LOG_INFO("Succeed to external sign ECC.");
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_ExternalVerify_ECC
* 功能描述： // 使用外部ECC公钥对ECC签名值进行验证
* 输入参数： // phSessionHandle          与密码设备已建立的会话句柄
                uiAlgID                  外部ECC算法标识
                pucPublicKey             外部ECC公钥结构
                pucDataInput             缓冲区指针，用于存放输入的数据
                uiInputLength            输入的数据长度
                pucSignature             缓冲区指针，用于存放输入的签名值数据
* 输出参数： //
* 返 回 值： // 0                        成功
                非0                      失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_ExternalVerify_ECC(IN void* hSessionHandle, IN unsigned int uiAlgID, IN ECCrefPublicKey *pucPublicKey, IN unsigned char *pucDataInput, IN unsigned int uiInputLength, IN ECCSignature *pucSignature)
{
    LOG_INFO("uiAlgID: 0x[{:08X}], pucDataInput: [{}]", uiAlgID, StringToHex((char*)pucDataInput, uiInputLength));

    uiAlgID = SGD_SM2_1;
    pqc::sdf::SDF_ExternalVerify_ECCRequest request;
    pqc::sdf::CommonResponse reply;
    grpc::ClientContext context;

    std::string asn1PubKey = SM2_PublicKey_0018ToASN1(pucPublicKey);
    if (asn1PubKey.empty())
    {
        LOG_ERROR("Failed to SM2_PublicKey_0018ToBinStr.");
        return -1;
    }
    LOG_INFO("pucPublicKey bin: 0x[{}]", StringToHex(asn1PubKey));

    std::string asn1Sig = SM2_Signature_0018ToASN1(pucSignature);
    if (asn1Sig.empty())
    {
        LOG_ERROR("Failed to call grpc SM2_Signature_0018ToBinStr.");
        return -1;
    }
    LOG_INFO("pucSignature bin: 0x[{}]", StringToHex(asn1Sig));

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_uialgid(uiAlgID);
    request.set_pucpublickey(asn1PubKey);
    request.set_pucdatainput(pucDataInput, uiInputLength);
    request.set_pucsignature(asn1Sig);
    grpc::Status status = g_grpcSdfStub->SDF_ExternalVerify_ECC(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_ExternalVerify_ECC status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_ExternalVerify_ECC, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    LOG_INFO("Succeed to external verify ECC.");
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_ExternalEncrypt_ECC
* 功能描述： // 使用外部ECC公钥对数据进行加密运算
* 输入参数： // phSessionHandle          与密码设备已建立的会话句柄
                uiAlgID                  ECC算法标志
                pucPublicKey             外部ECC公钥结构
                pucData                  缓冲区指针，用于存放输入的数据
                uiDataLength             输入的数据长度
* 输出参数： // pucEncData               缓冲区指针，用于存放输出的数据密文
* 返 回 值： // 0                        成功
                非0                      失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_ExternalEncrypt_ECC(IN void* hSessionHandle, IN unsigned int uiAlgID, IN ECCrefPublicKey *pucPublicKey, IN unsigned char *pucData, IN unsigned int uiDataLength, OUT ECCCipher *pucEncData)
{
    uiAlgID = SGD_SM2_3;

    pqc::sdf::SDF_ExternalEncrypt_ECCRequest request;
    pqc::sdf::SDF_ExternalEncrypt_ECCResponse reply;
    grpc::ClientContext context;

    std::string asn1PubKey = SM2_PublicKey_0018ToASN1(pucPublicKey);
    if (asn1PubKey.empty())
    {
        LOG_ERROR("Failed to SM2_PublicKey_0018ToBinStr.");
        return -1;
    }

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_uialgid(uiAlgID);
    request.set_pucpublickey(asn1PubKey);
    request.set_pucdata(pucData, uiDataLength);
    grpc::Status status = g_grpcSdfStub->SDF_ExternalEncrypt_ECC(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_ExternalEncrypt_ECC status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_ExternalEncrypt_ECC, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    int isBinStr;
    int nRet = SM2_Cipher_ASN1To0018(reply.pucencdata(), pucEncData, isBinStr);
    if (0 != nRet)
    {
        LOG_ERROR("Failed to SM2_Cipher_BinStrTo0018: [{}]", reply.pucencdata());
        return nRet;
    }

    return 0;
}

int SDF_ExternalDecrypt_ECC(IN void* hSessionHandle, IN unsigned int uiAlgID, IN ECCrefPrivateKey *pucPrivateKey, IN ECCCipher *pucEncData, OUT unsigned char *pucData, OUT unsigned int *puiDataLength)
{
    uiAlgID = SGD_SM2_3;
    pqc::sdf::SDF_ExternalDecrypt_ECCRequest request;
    pqc::sdf::SDF_ExternalDecrypt_ECCResponse reply;
    grpc::ClientContext context;

    std::string asn1Prikey = SM2_PrivateKey_0018ToASN1(pucPrivateKey);
    if (asn1Prikey.empty())
    {
        LOG_ERROR("Failed to call grpc SM2_PrivateKey_0018ToASN1.");
        return -1;
    }

    std::string asn1Cipher = SM2_Cipher_0018ToASN1(pucEncData);
    if (asn1Cipher.empty())
    {
        LOG_ERROR("Failed to SM2_Cipher_0018ToBinStr.");
        return -1;
    }

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_uialgid(uiAlgID);
    request.set_pucprivatekey(asn1Prikey);
    request.set_pucencdata(asn1Cipher);
    grpc::Status status = g_grpcSdfStub->SDF_ExternalDecrypt_ECC(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_ExternalDecrypt_ECC status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_ExternalDecrypt_ECC, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    std::string data = reply.pucdata();
    memcpy(pucData, &data[0], data.size());
    *puiDataLength = data.size();
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_InternalEncrypt_ECC
* 功能描述： // 使用内部ECC公钥对数据进行加密运算
* 输入参数： // phSessionHandle          与密码设备已建立的会话句柄
                uiIPKIndex               存储ECC密钥对的索引值
                uiAlgID                  ECC算法标志
                pucData                  缓冲区指针，用于存放输入的数据
                uiDataLength             输入的数据长度
* 输出参数： // pucEncData               缓冲区指针，用于存放输出的数据密文
* 返 回 值： // 0                        成功
                非0                      失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_InternalEncrypt_ECC(IN void* hSessionHandle, IN unsigned int uiIPKIndex, IN unsigned char* pucData, IN unsigned int uiDataLength, OUT ECCCipher *pucEncData)
{
    pqc::sdf::SDF_InternalEncrypt_ECCRequest request;
    pqc::sdf::SDF_InternalEncrypt_ECCResponse reply;
    grpc::ClientContext context;

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_uiipkindex(uiIPKIndex);
    request.set_pucdata(pucData, uiDataLength);
    grpc::Status status = g_grpcSdfStub->SDF_InternalEncrypt_ECC(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_InternalEncrypt_ECC status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_InternalEncrypt_ECC, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    int isBinStr;
    int nRet = SM2_Cipher_ASN1To0018(reply.pucencdata(), pucEncData, isBinStr);
    if (0 != nRet)
    {
        LOG_ERROR("Failed to SM2_Cipher_BinStrTo0018: [{}]", reply.pucencdata());
        return nRet;
    }
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_InternalDecrypt_ECC
* 功能描述： // 使用内部ECC私钥对数据进解密
* 输入参数： // phSessionHandle          与密码设备已建立的会话句柄
                uiISKIndex               存储ECC私钥的索引值
                uiAlgID                  ECC算法标志
                pucEncData               缓冲区指针，用于存放输入的数据密文
* 输出参数： // pucData                  缓冲区指针，用于存放输出的数据
                uiDataLength             输入的数据长度
* 返 回 值： // 0                        成功
                非0                      失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_InternalDecrypt_ECC(IN void* hSessionHandle, IN unsigned int uiISKIndex, IN ECCCipher *pucEncData, OUT unsigned char *pucData, OUT unsigned int *puiDataLength)
{
    pqc::sdf::SDF_InternalDecrypt_ECCRequest request;
    pqc::sdf::SDF_InternalDecrypt_ECCResponse reply;
    grpc::ClientContext context;

    std::string asn1Cipher = SM2_Cipher_0018ToASN1(pucEncData);
    if (asn1Cipher.empty())
    {
        LOG_ERROR("Failed to SM2_Cipher_0018ToBinStr.");
        return -1;
    }

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_uiiskindex(uiISKIndex);
    request.set_pucencdata(asn1Cipher);
    grpc::Status status = g_grpcSdfStub->SDF_InternalDecrypt_ECC(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_InternalDecrypt_ECC status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_InternalDecrypt_ECC, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    std::string data = reply.pucdata();
    memcpy(pucData, &data[0], data.size());
    *puiDataLength = data.size();
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_Encrypt
* 功能描述： // 使用密钥句柄和IV数据对数据进行对称加密
* 输入参数： // phSessionHandle          与密码设备已建立的会话句柄
                hKeyHandle               指定的密钥句柄
                uiAlgID                      算法标志，指定对称加密算法
                pucIV                        缓冲区指针，存放输入和返回的IV数据
                pucData                    缓冲区指针，用于存放输入的数据明文
                uiDataLength             输入的数据明文长度
* 输出参数： // pucEncData               缓冲区指针，用于存放输出的数据密文
                   puiEncDataLength         输出的数据密文长度
* 返 回 值： // 0                        成功
                    非0                      失败，返回错误码
* 其它说明： // 函数不对数据进行填充，输入的数据必须是指定算法分组长度的整数倍
***********************************************************************/
int SDF_Encrypt(IN void* hSessionHandle, IN void* hKeyHandle, IN unsigned int uiAlgID, INOUT unsigned char *pucIV,
                   IN unsigned char *pucData, IN unsigned int uiDataLength, OUT unsigned char *pucEncData, OUT unsigned int *puiEncDataLength)
{
    if (NULL == hKeyHandle)
    {
        LOG_ERROR("NULL key handle.");
        return -1;
    }

    pqc::sdf::EncryptRequest request;
    pqc::sdf::EncryptResponse reply;
    grpc::ClientContext context;

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_hkeyhandle(*(int64_t *)hKeyHandle);
    request.set_uialgid(uiAlgID);
    if (NULL != pucIV) {
        LOG_INFO("IV: 0x[{}]", StringToHex((char*)pucIV, 16));
        request.set_puciv(pucIV, 16);
    }
    else {
        LOG_INFO("Null IV.");
    }

    request.set_pucdata(pucData, uiDataLength);
    grpc::Status status = g_grpcSdfStub->SDF_Encrypt(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_Encrypt status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_Encrypt, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    std::string encData = reply.pucencdata();
    memcpy(pucEncData, &encData[0], encData.size());
    *puiEncDataLength = encData.size();
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_Decrypt
* 功能描述： // 使用密钥句柄和IV数据对数据进行对称解密
* 输入参数： // phSessionHandle          与密码设备已建立的会话句柄
                hKeyHandle               指定的密钥句柄
                uiAlgID                  算法标志，指定对称加密算法
                pucIV                    缓冲区指针，存放输入和返回的IV数据
                pucEncData               缓冲区指针，用于存放输入的数据密文
                uiEncDataLength          输入的数据密文长度
* 输出参数： // pucData                  缓冲区指针，用于存放输出的数据明文
                puiDataLength            输出的数据明文长度
* 返 回 值： // 0                        成功
                非0                      失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_Decrypt(IN void* hSessionHandle, IN void* hKeyHandle, IN unsigned int uiAlgID, INOUT unsigned char *pucIV,
                   IN unsigned char *pucEncData, IN unsigned int uiEncDataLength, OUT unsigned char *pucData, OUT unsigned int *puiDataLength)
{
    if (NULL == hKeyHandle)
    {
        LOG_ERROR("NULL key handle.");
        return -1;
    }

    pqc::sdf::DecryptRequest request;
    pqc::sdf::DecryptResponse reply;
    grpc::ClientContext context;

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_hkeyhandle(*(int64_t *)hKeyHandle);
    request.set_uialgid(uiAlgID);
    if (NULL != pucIV) {
        LOG_INFO("IV: 0x[{}]", StringToHex((char*)pucIV, 16));
        request.set_puciv(pucIV, 16);
    } else {
        LOG_INFO("Null IV.");
    }
    request.set_pucencdata(pucEncData, uiEncDataLength);
    grpc::Status status = g_grpcSdfStub->SDF_Decrypt(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_Decrypt status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_Decrypt, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    std::string data = reply.pucdata();
    memcpy(pucData, &data[0], data.size());
    *puiDataLength = data.size();
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_CalculateMAC
* 功能描述： // 使用密钥句柄和IV数据对数据进行MAC运算
* 输入参数： // phSessionHandle          与密码设备已建立的会话句柄
                hKeyHandle               指定的密钥句柄
                uiAlgID                  算法标志，指定MAC加密算法
                pucIV                    缓冲区指针，存放输入和返回的IV数据
                pucData                  缓冲区指针，用于存放输入的数据明文
                uiDataLength             输入的数据明文长度
* 输出参数： // pucMAC                   缓冲区指针，用于存放输出的MAC值
                puiMACLength             输出的MAC值长度
* 返 回 值： // 0                        成功
                非0                      失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_CalculateMAC(IN void* hSessionHandle, IN void* hKeyHandle, IN unsigned int uiAlgID, INOUT unsigned char *pucIV,
                        IN unsigned char *pucData, IN unsigned int uiDataLength, OUT unsigned char *pucMAC, OUT unsigned int *puiMACLength)
{
    if (NULL == hKeyHandle)
    {
        LOG_ERROR("NULL hKeyHandle.");
        return -1;
    }

    LOG_INFO("Start to cal MAC key handle: [{}], uiAlgID: 0x[{:08x}], uiDataLength: [{}]", *(int64_t*)hKeyHandle, uiAlgID, uiDataLength);

    pqc::sdf::SDF_CalculateMACRequest request;
    pqc::sdf::SDF_CalculateMACResponse reply;
    grpc::ClientContext context;

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_phkeyhandle(*(int64_t *)hKeyHandle);
    request.set_uialgid(uiAlgID);
    if (NULL != pucIV)
    {
        LOG_INFO("IV: 0x[{}]", StringToHex((char*)pucIV, 16));

        request.set_puciv(pucIV, 16);
    }
    request.set_pucdata(pucData, uiDataLength);
    grpc::Status status = g_grpcSdfStub->SDF_CalculateMAC(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_CalculateMAC status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_CalculateMAC, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    std::string mac = reply.pucmac();
    memcpy(pucMAC, &mac[0], mac.size());
    *puiMACLength = mac.size();

    LOG_INFO("Succeed to cal mac: 0x[{}], len: [{}]", StringToHex(mac), *puiMACLength);
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_HashInit
* 功能描述： // 三部杂凑运算第一步
* 输入参数： // phSessionHandle          与密码设备已建立的会话句柄
                uiAlgID                  指定杂凑算法标志
                pucPublicKey             签名者公钥，当uiAlgID为SGD_SM3时有效
                pucID                    签名者ID，当uiAlgID为SGD_SM3时有效
                uiIDLength               签名者ID长度，当uiAlgID为SGD_SM3时有效
* 输出参数： //
* 返 回 值： // 0                        成功
                非0                      失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_HashInit(IN void* hSessionHandle, IN unsigned int uiAlgID, IN ECCrefPublicKey *pucPublicKey, IN unsigned char *pucID, IN unsigned int uiIDLength)
{
    LOG_INFO("Start to hash init uiAlgID: [{:08x}]", uiAlgID);

    pqc::sdf::HashInitRequest request;
    pqc::sdf::CommonResponse reply;
    grpc::ClientContext context;

    if (NULL != pucPublicKey) {
        std::string asn1PubKey = SM2_PublicKey_0018ToASN1(pucPublicKey);
        if (asn1PubKey.empty())
        {
            LOG_ERROR("Failed to SM2_PublicKey_0018ToASN1.");
            return -1;
        }
        LOG_INFO("ASN1 pubkey: 0x[{}]", StringToHex(asn1PubKey));
        request.set_pucpublickey(asn1PubKey);
    }

    if (NULL != pucID && 0 < uiIDLength) {

        LOG_INFO("ID: 0x[{}], len: [{}]", StringToHex((char*)pucID, uiIDLength), uiIDLength);
        request.set_pucid(pucID, uiIDLength);
    }

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_uialgid(uiAlgID);
    grpc::Status status = g_grpcSdfStub->SDF_HashInit(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_HashInit status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_HashInit, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    LOG_INFO("Succeed to SDF_HashInit.");
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_HashUpdate
* 功能描述： // 三部杂凑运算第二步
* 输入参数： // phSessionHandle          与密码设备已建立的会话句柄
                pucData                  缓冲区指针，用于存放输入的数据明文
                uiDataLength             输入的数据明文长度
* 输出参数： //
* 返 回 值： // 0                        成功
                非0                      失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_HashUpdate(IN void* hSessionHandle, IN unsigned char *pucData, IN unsigned int uiDataLength)
{
    if (NULL == pucData || 0 >= uiDataLength)
    {
        LOG_ERROR("NULL or empty pucData.");
        return -1;
    }

    pqc::sdf::HashUpdateRequest request;
    pqc::sdf::CommonResponse reply;
    grpc::ClientContext context;

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_pucdata(pucData, uiDataLength);
    grpc::Status status = g_grpcSdfStub->SDF_HashUpdate(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_HashUpdate status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_HashUpdate, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

//  LOG_INFO("Succeed to hash update.");
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_HashFinal
* 功能描述： // 三部杂凑运算第三步
* 输入参数： // phSessionHandle          与密码设备已建立的会话句柄
* 输出参数： // pucHash                  缓冲区数据，用于存放输出的杂凑数据
                puiHashLength           返回杂凑数据的长度
* 返 回 值： // 0                        成功
                非0                      失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_HashFinal(IN void* hSessionHandle, OUT unsigned char *pucHash, OUT unsigned int *puiHashLength)
{
//  LOG_INFO("Start to hash final.");

    pqc::sdf::HashFinalRequest request;
    pqc::sdf::HashFinalResponse reply;
    grpc::ClientContext context;

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    grpc::Status status = g_grpcSdfStub->SDF_HashFinal(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_HashFinal status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_HashFinal, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    std::string data = reply.puchash();
    memcpy(pucHash, &data[0], data.size());
    *puiHashLength = data.size();

//  LOG_INFO("Succeed to hash final: 0x[{}], len: [{}]", StringToHex(data), *puiHashLength);
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_CreateFile
* 功能描述： // 在密码设备内部创建文件
* 输入参数： // phSessionHandle          与密码设备已建立的会话句柄
                pucFileName              缓冲区指针，用于存放输入的文件名，最大128字节
                uiNameLen                文件名长度
                uiFileSize               文件所占存储空间的长度
* 输出参数： //
* 返 回 值： // 0                        成功
                非0                      失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_CreateFile(IN void* hSessionHandle, IN unsigned char *pucFileName, IN unsigned int uiNameLen, IN unsigned int uiFileSize)
{
    LOG_INFO("pucFileName: [{}], uiNameLen: [{}], uiFileSize: [{}]", pucFileName, uiNameLen, uiFileSize);

    pqc::sdf::SDF_CreateFileRequest request;
    pqc::sdf::CommonResponse reply;
    grpc::ClientContext context;

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_pucfilename(pucFileName, uiNameLen);
    request.set_uifilesize(uiFileSize);
    grpc::Status status = g_grpcSdfStub->SDF_CreateFile(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_CreateFile status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_CreateFile, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    LOG_INFO("Succeed to SDF_CreateFile.");
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_ReadFile
* 功能描述： // 在密码设备内部读取文件
* 输入参数： // phSessionHandle          与密码设备已建立的会话句柄
                pucFileName              缓冲区指针，用于存放输入的文件名，最大128字节
                uiNameLen                文件名长度
                uiOffset                 读取文件时的偏移量
                puiFileLength            入参时指定读取文件的长度，出参时返回实际读取的长度
* 输出参数： // pucBuffer                缓冲区指针，用于存放读取的文件数据
* 返 回 值： // 0                        成功
                非0                      失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_ReadFile(IN void* hSessionHandle, IN unsigned char *pucFileName, IN unsigned int uiNameLen, IN unsigned int uiOffset, INOUT unsigned int *puiFileLength, OUT unsigned char *pucBuffer)
{
    LOG_INFO("pucFileName: [{}], uiNameLen: [{}], uiOffset: [{}]", pucFileName, uiNameLen, uiOffset);

    pqc::sdf::SDF_ReadFileRequest request;
    pqc::sdf::SDF_ReadFileResponse reply;
    grpc::ClientContext context;

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_pucfilename(pucFileName, uiNameLen);
    request.set_uioffset(uiOffset);
    request.set_puireadlength(*puiFileLength);
    grpc::Status status = g_grpcSdfStub->SDF_ReadFile(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_ReadFile status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_ReadFile, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    uint32_t readLen = reply.puireadlength();
    *puiFileLength = readLen;

    std::string buff = reply.pucbuffer();
    memcpy(pucBuffer, &buff[0], readLen);

    LOG_INFO("Succeed to read file len: [{}], data: [{}]", *puiFileLength, std::string((char*)pucBuffer, *puiFileLength));
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_WriteFile
* 功能描述： // 在密码设备内部写入文件
* 输入参数： // phSessionHandle          与密码设备已建立的会话句柄
                pucFileName              缓冲区指针，用于存放输入的文件名，最大128字节
                uiNameLen                文件名长度
                uiOffset                 写文件时的偏移量
                uiFileLength             指定写文件的长度
                pucBuffer                缓冲区指针，用于存放输入的写文件数据
* 输出参数： //
* 返 回 值： // 0                        成功
                非0                      失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_WriteFile(IN void* hSessionHandle, IN unsigned char *pucFileName, IN unsigned int uiNameLen, IN unsigned int uiOffset, IN unsigned int uiFileLength, IN unsigned char *pucBuffer)
{
    LOG_INFO("pucFileName: [{}], uiNameLen: [{}], uiOffset: [{}], uiFileLength: [{}]", pucFileName, uiNameLen, uiOffset, uiFileLength);

    pqc::sdf::SDF_WriteFileRequest request;
    pqc::sdf::CommonResponse reply;
    grpc::ClientContext context;

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_pucfilename(pucFileName, uiNameLen);
    request.set_uioffset(uiOffset);
    request.set_pucbuffer(pucBuffer, uiFileLength);
    request.set_uiwritelength(uiFileLength);
    grpc::Status status = g_grpcSdfStub->SDF_WriteFile(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_WriteFile status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_WriteFile, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    LOG_INFO("Succeed to SDF_WriteFile.");
    return 0;
}

/**********************************************************************
* 函数名称： // SDF_DeleteFile
* 功能描述： // 在密码设备内部删除指定文件
* 输入参数： // phSessionHandle          与密码设备已建立的会话句柄
                pucFileName              缓冲区指针，用于存放输入的文件名，最大128字节
                uiNameLen                文件名长度
* 输出参数： //
* 返 回 值： // 0                        成功
                非0                      失败，返回错误码
* 其它说明： //
***********************************************************************/
int SDF_DeleteFile(IN void* hSessionHandle, IN unsigned char *pucFileName, IN unsigned int uiNameLen)
{
    LOG_INFO("pucFileName: [{}], uiNameLen: [{}]", pucFileName, uiNameLen);
    pqc::sdf::SDF_DeleteFileRequest request;
    pqc::sdf::CommonResponse reply;
    grpc::ClientContext context;

    request.set_sessionhandle(*(int64_t*)hSessionHandle);
    request.set_pucfilename(pucFileName, uiNameLen);
    grpc::Status status = g_grpcSdfStub->SDF_DeleteFile(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc SDF_DeleteFile status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if(0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc SDF_DeleteFile, reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    LOG_INFO("Succeed to SDF_DeleteFile.");
    return 0;
}

/*
*输入参数：无
*输出参数：pubkey,pubkey_len,privkey,privkey_len
*返回值：是否成功
*/
int SDF_PQC_KemKeypair(int type, unsigned char *pubkey, int* pubkey_len, unsigned char *privkey, int* privkey_len)
{
    LOG_INFO("Start to kem_keypair type: [{}]", type);

    pqc::sdf::KemKeypairRequest request;
    pqc::sdf::KemKeypairResponse reply;

    grpc::ClientContext context;
    request.set_type((pqc::sdf::pqc_crypto_t)type);
    grpc::Status status = g_grpcSdfStub->SDF_PQC_KemKeypair(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if (0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc reply rv: [{}]", reply.rv());
        return reply.rv();
    }
    if (*pubkey_len < (int)reply.public_key_len()) {
        LOG_ERROR("Input pubkey_len: [{}] < output len: [{}]", *pubkey_len, reply.public_key_len());
        *pubkey_len = reply.public_key_len();
        *privkey_len = reply.private_key_len();
        return SDR_LENGTHERR;
    }

    if (*privkey_len < (int)reply.private_key_len()) {
        LOG_ERROR("Input privkey_len: [{}] < output len: [{}]", *privkey_len, reply.private_key_len());
        *pubkey_len = reply.public_key_len();
        *privkey_len = reply.private_key_len();
        return SDR_LENGTHERR;
    }

    memcpy(pubkey,reply.public_key().c_str(),reply.public_key_len());
    memcpy(privkey,reply.private_key().c_str(),reply.private_key_len());
    *pubkey_len = reply.public_key_len();
    *privkey_len = reply.private_key_len();

    LOG_INFO("Succeed to kem_keypair public key len: [{}], private key len: [{}]", *pubkey_len, *privkey_len);
    return 0;
}

/*
*输入参数：type,pubkey,pubkey_len,
*输出参数：shared_secret,shared_secret_len,ciphertext,ciphertext_len
*返回值：是否成功
*/
int SDF_PQC_KemEncaps(int type, const unsigned char *pubkey, int pubkey_len, unsigned char *shared_secret, int* shared_secret_len, unsigned char *ciphertext, int* ciphertext_len)
{
    LOG_INFO("Start to kem_encaps type: [{}], pubkey_len: [{}]", type, pubkey_len);

    pqc::sdf::KemEncapsRequest request;
    pqc::sdf::KemEncapsResponse reply;

    grpc::ClientContext context;
    request.set_type((pqc::sdf::pqc_crypto_t)type);
    request.mutable_public_key()->resize(pubkey_len);
    memcpy((void*)request.mutable_public_key()->c_str(),pubkey, pubkey_len);
    request.set_public_key_len(pubkey_len);
    grpc::Status status = g_grpcSdfStub->SDF_PQC_KemEncaps(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if (0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    if (*shared_secret_len < (int)reply.shared_secret_len()) {
        LOG_ERROR("Input shared_secret_len: [{}] < output len: [{}]", *shared_secret_len, reply.shared_secret_len());
        *shared_secret_len = reply.shared_secret_len();
        *ciphertext_len = reply.ciphertext_len();
        return SDR_LENGTHERR;
    }

    if (*ciphertext_len < (int)reply.ciphertext_len()) {
        LOG_ERROR("Input ciphertext_len: [{}] < output len: [{}]", *ciphertext_len, reply.ciphertext_len());
        *shared_secret_len = reply.shared_secret_len();
        *ciphertext_len = reply.ciphertext_len();
        return SDR_LENGTHERR;
    }
    memcpy(shared_secret,reply.shared_secret().c_str(),reply.shared_secret_len());
    memcpy(ciphertext,reply.ciphertext().c_str(),reply.ciphertext_len());
    *shared_secret_len = reply.shared_secret_len();
    *ciphertext_len = reply.ciphertext_len();

    LOG_INFO("Succeed to shared secret len: [{}], data: 0x[{}], cipher text len: [{}], data: 0x[{}]",
           *shared_secret_len, StringToHex((char*)shared_secret, *shared_secret_len),
           *ciphertext_len, StringToHex((char*)ciphertext, *ciphertext_len));
    return 0;
}

/*
*输入参数：type,ciphertext,ciphertext_len,privkey,privkey_len
*输出参数：shared_secret,shared_secret_len
*返回值：是否成功
*/
int SDF_PQC_KemDecaps(int type, const unsigned char *ciphertext, int ciphertext_len, const unsigned char *privkey, int privkey_len,unsigned char *shared_secret, int* shared_secret_len)
{
    LOG_INFO("Start to kem_decaps type: [{}], ciphertext_len: [{}], privkey_len: [{}]", type, ciphertext_len, privkey_len);

    pqc::sdf::KemDecapsRequest request;
    pqc::sdf::KemDecapsResponse reply;

    grpc::ClientContext context;
    request.set_type((pqc::sdf::pqc_crypto_t)type);
    request.mutable_ciphertext()->resize(ciphertext_len);
    memcpy((void*)request.mutable_ciphertext()->c_str(),ciphertext, ciphertext_len);
    request.set_ciphertext_len(ciphertext_len);
    request.mutable_private_key()->resize(privkey_len);
    memcpy((void*)request.mutable_private_key()->c_str(),privkey, privkey_len);
    request.set_private_key_len(privkey_len);
    grpc::Status status = g_grpcSdfStub->SDF_PQC_KemDecaps(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if (0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    if (*shared_secret_len < (int)reply.shared_secret_len()) {
        LOG_ERROR("Input shared_secret_len: [{}] < output len: [{}]", *shared_secret_len, reply.shared_secret_len());
        *shared_secret_len = reply.shared_secret_len();
        return SDR_LENGTHERR;
    }

      memcpy(shared_secret,reply.shared_secret().c_str(),reply.shared_secret_len());
      *shared_secret_len = reply.shared_secret_len();

      LOG_INFO("Succeed to kem_decaps shared_secret_len: [{}], data: 0x[{}]", *shared_secret_len, StringToHex((char*)shared_secret, *shared_secret_len));
      return 0;
}

/*
*输入参数：type
*输出参数：pubkey,pubkey_len,privkey,privkey_len
*返回值：是否成功
*/
int SDF_PQC_SigKeypair(int type, unsigned char *pubkey, int* pubkey_len, unsigned char *privkey, int* privkey_len)
{
    LOG_INFO("Start to sign_keypair type: [{}]", type);

    pqc::sdf::KemKeypairRequest request;
    pqc::sdf::KemKeypairResponse reply;

    grpc::ClientContext context;
    request.set_type((pqc::sdf::pqc_crypto_t)type);
    grpc::Status status = g_grpcSdfStub->SDF_PQC_SigKeypair(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if (0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    if (*pubkey_len < (int)reply.public_key_len()) {
        LOG_ERROR("Input pubkey_len: [{}] < output len: [{}]", *pubkey_len, reply.public_key_len());
        *pubkey_len = reply.public_key_len();
        *privkey_len = reply.private_key_len();
        return SDR_LENGTHERR;
    }

    if (*privkey_len < (int)reply.private_key_len()) {
        LOG_ERROR("Input ciphertext_len: [{}] < output len: [{}]", *privkey_len, reply.private_key_len());
        *pubkey_len = reply.public_key_len();
        *privkey_len = reply.private_key_len();
        return SDR_LENGTHERR;
    }

      memcpy(pubkey,reply.public_key().c_str(),reply.public_key_len());
      memcpy(privkey,reply.private_key().c_str(),reply.private_key_len());
      *pubkey_len = reply.public_key_len();
      *privkey_len = reply.private_key_len();

      LOG_INFO("Succeed to sign_keypair pubkey_len: [{}], pubkey: 0x[{}], privkey_len: [{}], privkey: 0x[{}]",
               *pubkey_len, StringToHex((char*)pubkey, *pubkey_len),
               *privkey_len, StringToHex((char*)privkey, *privkey_len));
      return 0;
}

/*
*输入参数：type,privkey,privkey_len,msg,msg_len
*输出参数：signature,signature_len
*返回值：是否成功
*/
int SDF_PQC_SigSign(int type, const unsigned char *privkey, int privkey_len, const unsigned char *msg, int msg_len, unsigned char *signature, int* signature_len)
{
    LOG_INFO("Start to sign_keypair type: [{}], privkey_len: [{}], msg_len: [{}]", type, privkey_len, msg_len);

    pqc::sdf::SigSignRequest request;
    pqc::sdf::SigSignResponse reply;

    grpc::ClientContext context;
    request.set_type((pqc::sdf::pqc_crypto_t)type);
    request.mutable_private_key()->resize(privkey_len);
    memcpy((void*)request.mutable_private_key()->c_str(),privkey, privkey_len);
    request.set_private_key_len(privkey_len);
    request.mutable_msg()->resize(msg_len);
    memcpy((void*)request.mutable_msg()->c_str(),msg, msg_len);
    request.set_msg_len(msg_len);
    grpc::Status status = g_grpcSdfStub->SDF_PQC_SigSign(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if (0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc reply rv: [{}]", reply.rv());
        return reply.rv();
    }
    if (*signature_len < (int)reply.signature_len()) {
        LOG_ERROR("Input signature_len: [{}] < output len: [{}]", *signature_len, reply.signature_len());
        *signature_len = reply.signature_len();
        return SDR_LENGTHERR;
    }

    memcpy(signature,reply.signature().c_str(),reply.signature_len());
    *signature_len = reply.signature_len();

    LOG_INFO("Succeed to sign_sign signature_len: [{}], signature: [{}]", *signature_len, StringToHex((char*)signature, *signature_len));
    return 0;
}

/*
*输入参数：type,msg,msg_len,signature,signature_len,pubkey,pubkey_len
*输出参数：无
*返回值：是否成功
*/
int SDF_PQC_SigVerify(int type, const unsigned char *msg, int msg_len, const unsigned char *signature, int signature_len, const unsigned char *pubkey, int pubkey_len)
{
    LOG_INFO("Start to sign_verify type: [{}], msg_len: [{}], signature_len: [{}], pubkey_len: [{}]", type, msg_len, signature_len, pubkey_len);

    pqc::sdf::SigVerifyRequest request;
    pqc::sdf::SigVerifyResponse reply;
    grpc::ClientContext context;

    request.set_type((pqc::sdf::pqc_crypto_t)type);

    request.mutable_msg()->resize(msg_len);
    memcpy((void*)request.mutable_msg()->c_str(),msg, msg_len);
    request.set_msg_len(msg_len);

    request.mutable_signature()->resize(signature_len);
    memcpy((void*)request.mutable_signature()->c_str(),signature, signature_len);
    request.set_signature_len(signature_len);

    request.mutable_public_key()->resize(pubkey_len);
    memcpy((void*)request.mutable_public_key()->c_str(),pubkey, pubkey_len);
    request.set_public_key_len(pubkey_len);
    grpc::Status status = g_grpcSdfStub->SDF_PQC_SigVerify(&context, request, &reply);
    if (!status.ok()) {
        LOG_ERROR("Failed to grpc status error code: [{}], error msg: [{}].", status.error_code(), status.error_message());
        return -1;
    }

    if (0 != reply.rv())
    {
        LOG_ERROR("Failed to call grpc reply rv: [{}]", reply.rv());
        return reply.rv();
    }

    LOG_INFO("Succeed to sign_verify.");
    return 0;
}
